简体   繁体   English

MySql:多个左联接使查询真的很慢

[英]MySql: Multiple Left Joins makes query really slow

Running the following query takes forever. 运行以下查询需要花费很长时间。 All the tables contain more than 200,000 records. 所有表包含超过200,000条记录。 Indexes exist on all the columns in the joining statements: 索引存在于连接语句的所有列中:

Select files.filename,
coalesce(temp_decmetadata.glare_roadGlare, 0) as glare_roadGlare,
coalesce(temp_decmetadata.glare_sun, 0) as glare_sun,
coalesce(temp_decmetadata.spray_heavySpray, 0) as spray_heavySpray,
coalesce(temp_kafaspdobjectdata.contrast_wellVisible, 0) as contrast_wellVisible,
coalesce(temp_kafaspdobjectdata.roadSafety_zebraCrossing, 0) as roadSafety_zebraCrossing,
coalesce(temp_visionmetadata.roadUser_bicycle, 0) as roadUser_bicycle,
coalesce(temp_visionmetadata.roadUser_car, 0) as roadUser_car,
coalesce(temp_visionmetadata.roadUser_pedestrian, 0) as roadUser_pedestrian
from files
left join 
(
 Select id,
 count(case when glare like '%roadGlare%' then 1 end) as glare_roadGlare,
 count(case when glare like '%sun%' then 1 end) as glare_sun,
 count(case when spray like '%heavySpray%' then 1 end) as spray_heavySpray
 from decmetadata
 group by id 
) temp_decmetadata on temp_decmetadata.id = files.id 
left join 
(
 Select id,
 count(case when contrast like '%wellVisible%' then 1 end) as contrast_wellVisible,
 count(case when roadSafety like '%zebraCrossing%' then 1 end) as roadSafety_zebraCrossing
 from kafaspdobjectdata
 group by id 
) temp_kafaspdobjectdata on temp_kafaspdobjectdata.id = files.id 
left join 
(
 Select id,
 count(case when roadUser like '%bicycle%' then 1 end) as roadUser_bicycle,
 count(case when roadUser like '%car%' then 1 end) as roadUser_car,
 count(case when roadUser like '%pedestrian%' then 1 end) as roadUser_pedestrian
 from visionmetadata
 group by id 
) temp_visionmetadata on temp_visionmetadata.id = files.id 

Result of "Explain Select..." is attached below: 以下是“解释选择...”的结果:

说明选择...

I'm not a MySQL specialist, but you can sure improve the sub-queries by moving the JOIN condition to the inner WHERE conditions and filtering the rows to only those that satisfies any CASE condition, this will decrease the number of rows that must be evaluated by the LIKE operator (this is the most expensive operation in this query). 我不是MySQL专家,但是您可以通过将JOIN条件移到内部WHERE条件并将行过滤为仅满足任何CASE条件的行来确保改善子查询,这将减少必须满足的行数。由LIKE运算符评估(这是此查询中最昂贵的操作)。 The following script should give you the idea: 以下脚本应该给您这个想法:

...
CROSS JOIN  (
  SELECT
  SUM(CASE WHEN glare LIKE '%roadGlare%' THEN 1 ELSE 0 END) AS glare_roadGlare,
  SUM(CASE WHEN glare LIKE '%sun%' THEN 1 ELSE 0 END) AS glare_sun,
  SUM(CASE WHEN spray LIKE '%heavySpray%' THEN 1 ELSE 0 END) AS spray_heavySpray
  FROM decmetadata
  WHERE ( id = files.id ) -- benefits from an index over DECMETADATA.ID
    AND ( 1=2
      OR glare LIKE '%roadGlare%'
      OR glare LIKE '%sun%'
      OR spray LIKE '%heavySpray%'
    )
) temp_decmetadata
...

Your query is well-structured. 您的查询结构良好。 The issue is all of the like '%xxx%' queries. 问题是所有like '%xxx%'查询。 Indexes will not help those clauses when you are substring matching like that. 当您像这样子字符串匹配时,索引将无法帮助这些子句。

Try using full text search instead. 请尝试使用全文搜索

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM