为什么即使使用LIMIT子句,查询在mysql中也需要很长时间?

时间:2012-11-28 23:42:50

标签: mysql

假设我有一个包含100多列和100万行的Order表。它在OrderID和FK约束StoreID上有一个PK - > Store.StoreID。

1)select * from 'Order' order by OrderID desc limit 10;

以上需要几毫秒。

2)select * from 'Order' o join 'Store' s on s.StoreID = o.StoreID order by OrderID desc limit 10;

这可能需要多达几秒钟。我添加的内连接越多,就会越慢。

3)select OrderID, column1 from 'Order' o join 'Store' s on s.StoreID = o.StoreID order by OrderID desc limit 10;

这似乎通过限制我们选择的列来加快执行速度。

我在这里有几点我不明白,如果有更多了解mysql(或者一般的rmdb查询执行)可以启发我的话,我会非常感激。

查询1很快,因为它只是PK的反向查找,而DB只需返回它遇到的前10行。

我不明白为什么查询2应该永远占用。操作不应该一样吗?即通过PK得到前10行,然后加入其他表。由于存在FK约束,因此可以保证满足关系。因此DB不需要连接超过必要的行,然后修剪结果,对吗?除非,FK约束允许空FK?在这种情况下,我猜左连接会比内连接快得多吗?

最后,我猜测查询3的速度更快,因为在这些不必要的连接中使用了更少的列?但是为什么在加入时查询执行需要其他列?它不应该首先使用PK加入,然后只获取10行的列吗?

谢谢!

2 个答案:

答案 0 :(得分:2)

我的理解是,在任何limit发生后,mysql引擎会应用join

来自http://dev.mysql.com/doc/refman/5.0/en/select.htmlThe HAVING clause is applied nearly last, just before items are sent to the client, with no optimization. (LIMIT is applied after HAVING.)

编辑:您可以尝试使用此查询来利用PK速度。

select * from (select * from 'Order' order by OrderID desc limit 10) o join 'Store' s on s.StoreID = o.StoreID;

答案 1 :(得分:2)

您的所有示例都要求现有表的表扫描,因此它们中的任何一个都不会比mysql可以缓存数据或结果的程度更高或更低。您的一些查询具有order by或join条件,这可以充分利用索引来使连接过程更有效,但是,这仍然与具有一组将触发索引使用的标准不同。

限制不是标准 - 一旦确定结果集,就可以将其视为过滤。一旦准备好结果集,就可以节省客户端上的时间,但不能在服务器上节省时间。

真的,获得您正在寻求的答案的唯一方法是熟悉:     EXPLAIN EXTENDED your_sql_statement

EXPLAIN的输出将显示mysql正在查看的行数,以及是否正在使用任何索引。