这需要72秒:
SELECT distinct(meters.id)
FROM meters, meters_tags, houses_tags, tags
WHERE (
tags.name = "xxx" AND ((
meters_tags.tag_id = tags.id AND
meters_tags.meter_id = meters.id
) OR (
houses_tags.tag_id = tags.id AND
houses_tags.house_id = meters.house_id
)
)
);
这需要0.00秒:
SELECT distinct(meters.id)
FROM meters, meters_tags, houses_tags, tags
WHERE (
tags.name = "xxx" AND ((
meters_tags.tag_id = tags.id AND
meters_tags.meter_id = meters.id
)
)
);
这需要0.00秒:
SELECT distinct(meters.id)
FROM meters, meters_tags, houses_tags, tags
WHERE (
tags.name = "xxx" AND ((
houses_tags.tag_id = tags.id AND
houses_tags.house_id = meters.house_id
)
)
);
这两个查询本身都不需要时间,但是将它们组合起来需要72秒。我还尝试将其转换为表单(query1)或(query),而不是query0和((query1)或(query2))并且速度也非常慢。
下面是第一个(慢速)查询的描述:
+----+-------------+-------------+-------+----------------------------------------------------------------------------------------------------+------------------------------------------+---------+-------+-------+-------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+-------+----------------------------------------------------------------------------------------------------+------------------------------------------+---------+-------+-------+-------------------------------------------------------+
| 1 | SIMPLE | meters_tags | index | index_meters_tags_on_tag_id_and_meter_id,index_meters_tags_on_tag_id,index_meters_tags_on_meter_id | index_meters_tags_on_tag_id_and_meter_id | 10 | NULL | 1 | Using index; Using temporary |
| 1 | SIMPLE | tags | ref | PRIMARY,tags_name | tags_name | 258 | const | 1 | Using where; Using index |
| 1 | SIMPLE | meters | index | PRIMARY,index_meters_on_house_id | index_meters_on_house_id | 5 | NULL | 45389 | Using index; Using join buffer |
| 1 | SIMPLE | houses_tags | index | index_houses_tags_on_tag_id_and_house_id | index_houses_tags_on_tag_id_and_house_id | 10 | NULL | 7158 | Using where; Using index; Distinct; Using join buffer |
+----+-------------+-------------+-------+----------------------------------------------------------------------------------------------------+------------------------------------------+---------+-------+-------+-------------------------------------------------------+
这些表都不大于10万行。当这两个查询单独运行得如此之快时,有什么可能需要如此长的时间来合并它们呢?似乎我需要的所有索引都存在,因为单独的子查询非常快。
最佳答案
仔细观察您的组合查询;它计算houses_标记与meters_标记的交叉连接,排序并消除重复项,并将其连接到查询的其余部分。两个yur部分查询都会立即删除houses_标记或meters_标记,并且只使用othr。因此出现了惊人的速度差异。
建议:学习并使用现代连接语法,如果不是因为其他原因,而是因为它将帮助您避免这些病理病例,直到您学会识别它们。
关于mysql - 糟糕的SQL性能,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15574210/