【发布时间】:2013-03-22 15:34:32
【问题描述】:
这需要 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) OR (query) 而不是 query0 AND ((query1) OR (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 |
+----+-------------+-------------+-------+----------------------------------------------------------------------------------------------------+------------------------------------------+---------+-------+-------+-------------------------------------------------------+
这些表的行数都不超过 100k。当这两个查询单独运行得如此之快时,合并这两个查询可能需要这么长时间?似乎我需要的所有索引都存在,因为仅子查询就足够快了。
【问题讨论】:
-
它没有回答这个问题,但你可以做
(fastquery1) union all (fastquery2)。这是我在查询被ORs 减慢时使用的技巧。 -
谢谢。此查询是自动生成的 - 可以将多个子句添加到查询中,每个子句用 AND 分隔。使用 union all 会破坏这种模式,但没关系,我可以对这个子句进行特殊处理,因为似乎没有有效的方法可以将其表示为“正常”子句。
标签: mysql performance