2011-06-22 23 views
15

Estoy usando un objeto PDO en PHP para ejecutar consultas MYSQL, y he estado tratando de trabajar en una consulta para acelerarlo. La consulta es la siguiente, como se ve en mi archivo PHP:

PDO mucho más lento que la consulta mysql?

$query = 
"SELECT SQL_NO_CACHE f.position, s.item_id, s.item_type, s.title, s.caption, s.date 
FROM apiv2.search_all s 
INNER JOIN apiv2.tags t 
USING(item_id, item_type) 
LEFT JOIN apiv2.featured f 
ON t.item_id = f.item_id AND t.item_type = f.item_type AND f.feature_type = :id 
WHERE t.tag = 'FeaturedContent' 
ORDER BY position IS NULL, position ASC, date"; 

$mysql_vars[':id'] = $id; 
$stmt = $connection->prepare($query); 
$stmt->execute($vars); 
$data = $stmt->fetchAll(PDO::FETCH_ASSOC); 

Esta consulta se ejecuta significativamente diferente dependiendo de si incluyo la cláusula ORDER BY, pero sólo en la consola de MySQL:

- MYSQL Console with ORDER BY: 1.07 sec 
    - starting 0.000141 
    - Opening tables 0.001416 
    - System lock 0.000003 
    - Table lock 0.000007 
    - init 0.000021 
    - checking permissions 0.000001 
    - checking permissions 0.000036 
    - optimizing 0.000027 
    - statistics 0.000027 
    - preparing 0.000015 
    - Creating tmp table 0.003440 
    - executing 0.000001 
    - Copying to tmp table 1.050029 
    - Sorting result 0.013097 
    - Sending data 0.000295 
    - end 0.000002 
    - removing tmp table 0.002045 
    - end 0.000003 
    - query end 0.000002 
    - freeing items 0.000331 
    - logging slow query 0.000002 
    - cleaning up 0.000007 
- MYSQL Console unordered output: .0053 sec 
    - starting 0.000076 
    - Opening tables 0.001506 
    - System lock 0.000002 
    - Table lock 0.000005 
    - init 0.000015 
    - checking permissions 0.000001 
    - checking permissions 0.000022 
    - optimizing 0.000012 
    - statistics 0.000021 
    - preparing 0.000011 
    - executing 0.000001 
    - Sending data 0.002895 
    - end 0.000002 
    - query end 0.000001 
    - freeing items 0.000078 
    - logging slow query 0.000000 
    - cleaning up 0.000002 
- PDO Prepared stmt ORDER BY: 1.18 sec 
    - 'Status' => 'starting', 'Duration' => '0.000147' 
    - 'Status' => 'Opening tables', 'Duration' => '0.000784' 
    - 'Status' => 'System lock', 'Duration' => '0.000004' 
    - 'Status' => 'Table lock', 'Duration' => '0.000007' 
    - 'Status' => 'init', 'Duration' => '0.000017' 
    - 'Status' => 'checking permissions', 'Duration' => '0.000002' 
    - 'Status' => 'checking permissions', 'Duration' => '0.000028' 
    - 'Status' => 'optimizing', 'Duration' => '0.000018' 
    - 'Status' => 'statistics', 'Duration' => '0.000026' 
    - 'Status' => 'preparing', 'Duration' => '0.000014' 
    - 'Status' => 'Creating tmp table', 'Duration' => '0.002112' 
    - 'Status' => 'executing', 'Duration' => '0.000001' 
    - 'Status' => 'Copying to tmp table', 'Duration' => '1.033056' 
    - 'Status' => 'Sorting result', 'Duration' => '0.013759' 
    - 'Status' => 'Sending data', 'Duration' => '0.073144' 
    - 'Status' => 'end', 'Duration' => '0.000003' 
    - 'Status' => 'removing tmp table', 'Duration' => '0.001999' 
    - 'Status' => 'end', 'Duration' => '0.000004' 
    - 'Status' => 'query end', 'Duration' => '0.000007' 
    - 'Status' => 'freeing items', 'Duration' => '0.000118' 
    - 'Status' => 'logging slow query', 'Duration' => '0.000001' 
    - 'Status' => 'cleaning up', 'Duration' => '0.000003' 
- PDO Prepared stmt unordered output: 1.06 sec 
    - 'Status' => 'starting', 'Duration' => '0.000074' 
    - 'Status' => 'Opening tables', 'Duration' => '0.001364' 
    - 'Status' => 'System lock', 'Duration' => '0.000004' 
    - 'Status' => 'Table lock', 'Duration' => '0.000007' 
    - 'Status' => 'init', 'Duration' => '0.000017' 
    - 'Status' => 'checking permissions', 'Duration' => '0.000001' 
    - 'Status' => 'checking permissions', 'Duration' => '0.000026' 
    - 'Status' => 'optimizing', 'Duration' => '0.000015' 
    - 'Status' => 'statistics', 'Duration' => '0.000027' 
    - 'Status' => 'preparing', 'Duration' => '0.000013' 
    - 'Status' => 'executing', 'Duration' => '0.000002' 
    - 'Status' => 'Sending data', 'Duration' => '1.048216' 
    - 'Status' => 'end', 'Duration' => '0.000003' 
    - 'Status' => 'query end', 'Duration' => '0.000001' 
    - 'Status' => 'freeing items', 'Duration' => '0.000122' 
    - 'Status' => 'logging slow query', 'Duration' => '0.000001' 
    - 'Status' => 'cleaning up', 'Duration' => '0.000003' 
- MYSQL functions from PHP unordered: 1.09 sec 
    - 'Status' => 'starting', 'Duration' => '0.000109' 
    - 'Status' => 'checking permissions', 'Duration' => '0.000002' 
    - 'Status' => 'checking permissions', 'Duration' => '0.000001' 
    - 'Status' => 'checking permissions', 'Duration' => '0.000004' 
    - 'Status' => 'Opening tables', 'Duration' => '0.002101' 
    - 'Status' => 'System lock', 'Duration' => '0.000004' 
    - 'Status' => 'Table lock', 'Duration' => '0.000009' 
    - 'Status' => 'init', 'Duration' => '0.000032' 
    - 'Status' => 'checking permissions', 'Duration' => '0.000003' 
    - 'Status' => 'checking permissions', 'Duration' => '0.000057' 
    - 'Status' => 'optimizing', 'Duration' => '0.000033' 
    - 'Status' => 'statistics', 'Duration' => '0.000065' 
    - 'Status' => 'preparing', 'Duration' => '0.000032' 
    - 'Status' => 'executing', 'Duration' => '0.000005' 
    - 'Status' => 'Sending data', 'Duration' => '1.000079' 
    - 'Status' => 'end', 'Duration' => '0.000005' 
    - 'Status' => 'query end', 'Duration' => '0.000002' 
    - 'Status' => 'freeing items', 'Duration' => '0.000300' 
    - 'Status' => 'logging slow query', 'Duration' => '0.000001' 
    - 'Status' => 'cleaning up', 'Duration' => '0.000007' 
- MYSQL functions from PHP w/ ORDER BY: 1.09 sec 
    - 'Status' => 'starting', 'Duration' => '0.000148' 
    - 'Status' => 'checking permissions', 'Duration' => '0.000001' 
    - 'Status' => 'checking permissions', 'Duration' => '0.000001' 
    - 'Status' => 'checking permissions', 'Duration' => '0.000001' 
    - 'Status' => 'Opening tables', 'Duration' => '0.000559' 
    - 'Status' => 'System lock', 'Duration' => '0.000002' 
    - 'Status' => 'Table lock', 'Duration' => '0.000006' 
    - 'Status' => 'init', 'Duration' => '0.000019' 
    - 'Status' => 'checking permissions', 'Duration' => '0.000001' 
    - 'Status' => 'checking permissions', 'Duration' => '0.000030' 
    - 'Status' => 'optimizing', 'Duration' => '0.000018' 
    - 'Status' => 'statistics', 'Duration' => '0.000025' 
    - 'Status' => 'preparing', 'Duration' => '0.000015' 
    - 'Status' => 'Creating tmp table', 'Duration' => '0.001828' 
    - 'Status' => 'executing', 'Duration' => '0.000001' 
    - 'Status' => 'Copying to tmp table', 'Duration' => '0.958071' 
    - 'Status' => 'Sorting result', 'Duration' => '0.013502' 
    - 'Status' => 'Sending data', 'Duration' => '0.088148' 
    - 'Status' => 'end', 'Duration' => '0.000003' 
    - 'Status' => 'removing tmp table', 'Duration' => '0.002037' 
    - 'Status' => 'end', 'Duration' => '0.000003' 
    - 'Status' => 'query end', 'Duration' => '0.000001' 
    - 'Status' => 'freeing items', 'Duration' => '0.000112' 
    - 'Status' => 'logging slow query', 'Duration' => '0.000001' 
    - 'Status' => 'cleaning up', 'Duration' => '0.000004' 

explica:

de ordenar

|-id-|-select_type-|-table----|-type---|-possible_keys--------|-key-----------------|-key_len-|-ref-------------------------------------|-rows--|-Extra 
|-1--|-SIMPLE------|-s--------|-ALL----|-PRIMARY,search_index-|-NULL----------------|-NULL----|-NULL------------------------------------|-92166-|-Using temporary; Using filesort 
|-1--|-SIMPLE------|-tags-----|-eq_ref-|-PRIMARY--------------|-PRIMARY-------------|-426-----|-apiv2.s.item_id,apiv2.s.item_type,const-|-1-----|-Using where; Using index 
|-1--|-SIMPLE------|-featured-|-ref----|-type_position_index--|-type_position_index-|-62------|-const-----------------------------------|-3-----|-Using index 

sin necesidad de ordenar

|-id-|-select_type-|-table----|-type---|-possible_keys--------|-key-----------------|-key_len-|-ref-------------------------------------|-rows--|-Extra 
|-1--|-SIMPLE------|-s--------|-ALL----|-PRIMARY,search_index-|-NULL----------------|-NULL----|-NULL------------------------------------|-88346-|- 
|-1--|-SIMPLE------|-tags-----|-eq_ref-|-PRIMARY--------------|-PRIMARY-------------|-426-----|-apiv2.s.item_id,apiv2.s.item_type,const-|-1-----|-Using where; Using index 
|-1--|-SIMPLE------|-featured-|-ref----|-type_position_index--|-type_position_index-|-62------|-const-----------------------------------|-3-----|-Using index 

tabla: search_all

CREATE TABLE `search_all` ( 
    `item_id` varchar(20) NOT NULL DEFAULT '', 
    `item_type` varchar(20) NOT NULL DEFAULT '', 
    `title` varchar(255) DEFAULT NULL, 
    `caption` text, 
    `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    PRIMARY KEY (`item_id`,`item_type`), 
    UNIQUE KEY `search_index` (`item_id`,`item_type`,`date`), 
    KEY `date_index` (`date`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 


|-id-|-select_type-|-table------|-type-|-possible_keys-|-key--|-key_len-|-ref--|-rows--|-Extra 
|-1--|-SIMPLE------|-search_all-|-ALL--|-NULL----------|-NULL-|-NULL----|-NULL-|-74785-|- 

tabla: etiquetas

CREATE TABLE `tags` ( 
    `tag` varchar(100) NOT NULL DEFAULT '', 
    `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `item_id` varchar(20) NOT NULL DEFAULT '', 
    `item_type` varchar(20) NOT NULL DEFAULT '', 
    PRIMARY KEY (`item_id`,`item_type`,`tag`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 


|-id-|-select_type-|-table-|-type--|-possible_keys-|-key-----|-key_len-|-ref--|-rows---|-Extra 
|-1--|-SIMPLE------|-tags--|-index-|-NULL----------|-PRIMARY-|-426-----|-NULL-|-197400-|-Using index 

TABLA: Favoritos

CREATE TABLE `featured` ( 
    `position` int(10) NOT NULL DEFAULT '0', 
    `item_type` varchar(20) NOT NULL DEFAULT '', 
    `item_id` varchar(20) NOT NULL DEFAULT '', 
    `feature_type` varchar(20) NOT NULL DEFAULT '', 
    PRIMARY KEY (`position`,`item_type`,`item_id`,`feature_type`), 
    KEY `type_position_index` (`feature_type`,`position`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 


|-id-|-select_type-|-table----|-type--|-possible_keys-|-key-----------------|-key_len-|-ref--|-rows-|-Extra 
|-1--|-SIMPLE------|-featured-|-index-|-NULL----------|-type_position_index-|-66------|-NULL-|-13---|-Using index 

¿Por qué no hay diferencia entre el desordenamiento en el PDO o MSQL de PHP? ¿Hay alguna manera de que pueda hacerlo más rápido?

+3

Publique las definiciones de tablas (incluidos los índices) y el plan de ejecución (EXPLAIN) de la consulta. –

+0

¿Realmente puedes reproducir esto? El "envío de datos" parece consumir demasiado tiempo en el último ejemplo. Tal vez es solo un "retraso", o un problema de almacenamiento en caché. – KingCrunch

+1

Creo que la hora se comprueba al comienzo de cada paso en el perfil, lo que significa que las largas son en realidad una mala revisión del paso anterior, que apuntaría a todos los dedos en el paso – Ripptor

Respuesta

5

A menos que su pedido sea para una columna indexada y el optimizador considere que es una buena idea usar el índice, un "ORDENAR" dará como resultado un tipo de tiempo y recursos considerables para cualquier conjunto de resultados de cualquier tamaño.

El motivo por el cual la versión de PDO tarda más es que su secuencia de comandos consume filas más lentas de lo que SQLServer puede proporcionarles, por lo que la base de datos está esperando su programa. Como está utilizando un lenguaje interpretado y una API que hace una cantidad considerable de manipulación del resultado de la fila, esto es de esperar. Este retraso en el "envío de datos" es mucho mayor (0,75 segundos y 1,04 segundos) que la sobrecarga del tipo.

Tenga en cuenta que la recuperación lenta se complica por el orden de. En el caso del SQL no ordenado, las filas se enviarán tan pronto como se seleccionen. En el caso de la selección ordenada, todas las filas se seleccionarán y luego se ordenarán antes de que se envíe la primera fila de resultados.

+1

Tengo un índice sobre la posición, pero como la mayoría de las filas no están unidas a las presentadas, la mayoría no tendrá una posición. Había implementado una ordenación PHP para omitir la clasificación en el lado MYSQL, pero como eliminar el género no lo aceleró, no tengo ninguna mejora. Si pudiera acelerar el PDO desordenado, entonces creo que podría funcionar. ¿Tienes alguna sugerencia sobre eso? – Ripptor

0

¿Puede por favor publicar las definiciones de las tablas (campos, tipos de campos, etc.)?

yo primero añadir un índice simple de date en la tabla search_all y

un índice simple de tag en la tabla tags.

+0

Definiciones de tablas agregadas. Hay un índice de fecha en search_all, y la tabla de etiquetas es triple (item_id, item_type, tag) – Ripptor

+0

@Ripptor: Un índice '(tag)' es muy diferente que index '(item_id, item_type, tag)' –

Cuestiones relacionadas