La consulta que tengo es para una tabla de inventario. Lo que hace la subconsulta de unión es obtener la cantidad total de órdenes de trabajo que hay para cada activo de inventario. Si ejecuto la consulta base con las combinaciones principales para el tipo de equipo, proveedor, ubicación y sala, funciona perfectamente. Menos de un segundo para devolver un resultado. usándolo con la combinación de subconsulta, tarda de 15 a 20 segundos en devolver un resultado.¿Cómo puedo acelerar mi consulta? la subconsulta es demasiado lenta
Ésta es la consulta completa:
SELECT `inventory`.inventory_id AS 'inventory_id',
`inventory`.media_tag AS 'media_tag',
`inventory`.asset_tag AS 'asset_tag',
`inventory`.idea_tag AS 'idea_tag',
`equipTypes`.equipment_type AS 'equipment_type',
`inventory`.equip_make AS 'equip_make',
`inventory`.equip_model AS 'equip_model',
`inventory`.equip_serial AS 'equip_serial',
`inventory`.sales_order AS 'sales_order',
`vendors`.vendor_name AS 'vendor_name',
`inventory`.purchase_order AS 'purchase_order',
`status`.status AS 'status',
`locations`.location_name AS 'location_name',
`rooms`.room_number AS 'room_number',
`inventory`.notes AS 'notes',
`inventory`.send_to AS 'send_to',
`inventory`.one_to_one AS 'one_to_one',
`enteredBy`.user_name AS 'user_name',
from_unixtime(`inventory`.enter_date, '%m/%d/%Y') AS 'enter_date',
from_unixtime(`inventory`.modified_date, '%m/%d/%Y') AS 'modified_date',
COALESCE(at.assets,0) AS assets
FROM mod_inventory_data AS `inventory`
LEFT JOIN mod_inventory_equip_types AS `equipTypes`
ON `equipTypes`.equip_type_id = `inventory`.equip_type_id
LEFT JOIN mod_vendors_main AS `vendors`
ON `vendors`.vendor_id = `inventory`.vendor_id
LEFT JOIN mod_inventory_status AS `status`
ON `status`.status_id = `inventory`.status_id
LEFT JOIN mod_locations_data AS `locations`
ON `locations`.location_id = `inventory`.location_id
LEFT JOIN mod_locations_rooms AS `rooms`
ON `rooms`.room_id = `inventory`.room_id
LEFT JOIN mod_users_data AS `enteredBy`
ON `enteredBy`.user_id = `inventory`.entered_by
LEFT JOIN
(SELECT asset_tag, count(*) AS assets
FROM mod_workorder_data
WHERE asset_tag IS NOT NULL
GROUP BY asset_tag) AS at
ON at.asset_tag = inventory.asset_tag
ORDER BY inventory_id ASC LIMIT 0,20
El MySQL datos de explicación para esto es que aquí
+----+-------------+--------------------+--------+---------------+-----------+---------+-------------------------------------+-------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+--------+---------------+-----------+---------+-------------------------------------+-------+---------------------------------+
| 1 | PRIMARY | inventory | ALL | NULL | NULL | NULL | NULL | 12612 | Using temporary; Using filesort |
| 1 | PRIMARY | equipTypes | eq_ref | PRIMARY | PRIMARY | 4 | spsd_woidbs.inventory.equip_type_id | 1 | |
| 1 | PRIMARY | vendors | eq_ref | PRIMARY | PRIMARY | 4 | spsd_woidbs.inventory.vendor_id | 1 | |
| 1 | PRIMARY | status | eq_ref | PRIMARY | PRIMARY | 4 | spsd_woidbs.inventory.status_id | 1 | |
| 1 | PRIMARY | locations | eq_ref | PRIMARY | PRIMARY | 4 | spsd_woidbs.inventory.location_id | 1 | |
| 1 | PRIMARY | rooms | eq_ref | PRIMARY | PRIMARY | 4 | spsd_woidbs.inventory.room_id | 1 | |
| 1 | PRIMARY | enteredBy | eq_ref | PRIMARY | PRIMARY | 4 | spsd_woidbs.inventory.entered_by | 1 | |
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 4480 | |
| 2 | DERIVED | mod_workorder_data | range | asset_tag | asset_tag | 13 | NULL | 15897 | Using where; Using index |
+----+-------------+--------------------+--------+---------------+-----------+---------+-------------------------------------+-------+---------------------------------+
uso de perfiles de consulta MySQL me sale esto:
+--------------------------------+------------+
| Status | Time |
+--------------------------------+------------+
| starting | 0.000020 |
| checking query cache for query | 0.000263 |
| Opening tables | 0.000034 |
| System lock | 0.000013 |
| Table lock | 0.000079 |
| optimizing | 0.000011 |
| statistics | 0.000138 |
| preparing | 0.000019 |
| executing | 0.000010 |
| Sorting result | 0.000004 |
| Sending data | 0.015103 |
| init | 0.000094 |
| optimizing | 0.000009 |
| statistics | 0.000049 |
| preparing | 0.000022 |
| Creating tmp table | 0.000104 |
| executing | 0.000009 |
| Copying to tmp table | 15.410168 |
| Sorting result | 0.009488 |
| Sending data | 0.000215 |
| end | 0.000006 |
| removing tmp table | 0.001997 |
| end | 0.000018 |
| query end | 0.000005 |
| freeing items | 0.000112 |
| storing result in query cache | 0.000011 |
| removing tmp table | 0.000022 |
| closing tables | 0.000036 |
| logging slow query | 0.000005 |
| logging slow query | 0.000005 |
| cleaning up | 0.000013 |
+--------------------------------+------------+
que me muestra que el cuello de la botella está copiando a la mesa temporal, pero no estoy seguro de cómo acelerarlo. ¿Hay configuraciones en el servidor que puedo configurar para que esto sea más rápido? ¿Hay cambios en la consulta existente que pueda hacer que produzcan los mismos resultados que serían más rápidos?
Me parece que la subconsulta LEFT JOIN daría la misma matriz de datos resultante cada vez, así que si tiene que ejecutar esa consulta para cada fila en la lista de inventario, puedo ver por qué sería lenta. ¿O MySQL almacena en caché la subconsulta cuando se ejecuta? Creí leer en algún lugar que MySQL no almacena en caché las subconsultas, ¿es así?
Cualquier ayuda es apreciada.
¿Cuántos datos hay en estas tablas que está consultando? ¿Y se ha asegurado de que todas las columnas que está utilizando para sus predicados de unión estén indexadas? –
La tabla de datos de inventario tiene 12,612 registros y la tabla de datos de órdenes de trabajo en la subconsulta tiene 19,159 registros. Tengo índices para todos los campos ID y el campo asset_tag usado en los JOIN. Quise indicar eso en la publicación original, pero lo olvidé. ¿Debo tenerlos todos en un solo índice? Actualmente tengo índices separados. Por cierto, gracias por reformatear la publicación. –
Hmm. Eso no suena como una cantidad masiva de datos y no creo que la combinación de índices genere mucho impulso. Para solucionar el problemaproblema, realmente comenzaría por desmantelar la consulta. Elimine una unión a la vez y compare el rendimiento. Hacerlo puede revelar un problema en alguna parte. Tal vez comience eliminando la subconsulta y vea cómo funciona. Si solo es el culpable, una opción puede ser desnormalizar los datos y crear una tabla que contenga esos conteos. –