2

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

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 行。

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

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

谢谢!

4

2 回答 2

2

我的理解是 mysql 引擎limit在任何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;

于 2012-11-28T23:49:19.837 回答
2

您的所有示例都要求对现有表进行表扫描,因此它们的性能都不会超过 mysql 可以缓存数据或结果的程度。您的某些查询具有 order by 或 join 条件,这可以纯粹利用索引来提高连接过程的效率,但是,这仍然与拥有一组将触发使用索引的条件不同。

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

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

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

于 2012-11-28T23:51:50.380 回答