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?
Publique las definiciones de tablas (incluidos los índices) y el plan de ejecución (EXPLAIN) de la consulta. –
¿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
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