微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何加快查询速度子查询太慢

如何解决如何加快查询速度子查询太慢

| 我的查询是针对库存表的。子查询联接所做的是获取每个库存资产的工作订单总数。如果我使用基本联接来运行基本查询,以查询设备类型,供应商,位置和房间,则它运行得很好。不到一秒即可返回结果。将其与子查询联接一起使用,需要15到20秒才能返回结果。 这是完整的查询
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
这里的MysqL EXPLAIN数据在这里
+----+-------------+--------------------+--------+---------------+-----------+---------+-------------------------------------+-------+---------------------------------+
| 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        |
+----+-------------+--------------------+--------+---------------+-----------+---------+-------------------------------------+-------+---------------------------------+
使用MySQL查询分析我得到这个:
+--------------------------------+------------+
| 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  |
+--------------------------------+------------+
这告诉我瓶颈正在复制到临时表,但是我不确定如何加快速度。我可以配置服务器端上的设置以使其更快吗?我可以对现有查询进行哪些更改,以产生与更快结果相同的结果? 在我看来,LEFT JOIN子查询每次都会给出相同的结果数据矩阵,因此,如果必须对清单列表中的每一行运行该查询,我可以明白为什么它会很慢。还是MysqL在运行时会缓存子查询?我以为我读过MysqL不缓存子查询的地方,这是真的吗? 任何帮助表示赞赏。     

解决方法

这是我所做的,似乎运作良好。我创建了一个名为mod_workorder_counts的表。该表有两个字段,资产标签是唯一的,而wo_count是和INT(3)字段。我用以下查询填充该表:
INSERT INTO mod_workorder_counts ( asset_tag,wo_count ) 
select s.asset_tag,ct 
FROM
  ( SELECT t.asset_tag,count(*) as ct
    FROM mod_workorder_data t
    WHERE t.asset_tag IS NOT NULL
    GROUP BY t.asset_tag
  ) as s
ON DUPLICATE KEY UPDATE mod_workorder_counts.wo_count = ct
在0.1580秒内执行,这可能会稍微慢一些,但还不错。 现在,当我对原始查询运行此修改时:
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.wo_count,0) AS workorders 
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 mod_workorder_counts AS at  
       ON at.asset_tag = inventory.asset_tag 
ORDER BY inventory_id ASC LIMIT 0,20
它在0.0051秒内执行。两次查询之间的总和为0.1631秒,接近1/10秒,而原始子查询为15+秒。 如果仅使用“ wo_count \”字段而不使用COALESCE,则对于未在“ mod_workorder_counts \”表中列出的所有资产标签,我都会得到NULL值。因此,对于任何NULL值,COALESCE都会给我0,这就是我想要的。 现在,我将对其进行设置,以便在为资产标签输入工单时,我将对Counts表进行更新的INSERT / UPDATE查询,这样它就不会不必要地运行。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。