【发布时间】:2012-10-07 11:24:56
【问题描述】:
我有一个表 foo 与(以及其他 20 个)列 bar、baz 和 quux 索引在 baz 和 quux。该表有大约 500k 行。
为什么以下查询的速度差异如此之大?查询 A 耗时 0.3s,查询 B 耗时 28s。
查询 A
select baz from foo
where bar = :bar
and quux = (select quux from foo where bar = :bar order by quux desc limit 1)
解释
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY foo ref quuxIdx quuxIdx 9 const 2 "Using where"
2 SUBQUERY foo index NULL quuxIdx 9 NULL 1 "Using where"
查询 B
select baz from foo
where bar = :bar
and quux = (select MAX(quux) from foo where bar = :bar)
解释
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY foo ref quuxIdx quuxIdx 9 const 2 "Using where"
2 SUBQUERY foo ALL NULL NULL NULL NULL 448060 "Using where"
我使用 MySQL 5.1.34。
【问题讨论】:
-
'LiMIT 1' 表示取 1 行并停止,不是吗?查询 B 是 O(n*m)
-
@PaulDinh 似乎两个查询都产生相同的结果,很可能与操作顺序有关,在第一种情况下,它按 quux 排序,并在第二个查询中从结果(快速)中搜索栏(需要检查整个表)从未排序然后排序找到最大值
-
@Viktor,你能告诉我
explain select baz from foo where bar = :bar and quux = (select quux from foo where quux=MAX(quux) and bar = :bar )explain select baz from foo where bar = :bar and quux = (select quux from foo where quux=MAX(quux) and bar = :bar limit 1 ) -
@eicto:+1 对您的评论,但我想澄清一件事:查找未索引列的最大值不需要 O(n log(n)) 排序。它可以通过扫描表一次并记住看到的最高值在 O(n) 时间内完成。
标签: mysql performance query-optimization