2012-11-28 27 views
1

假设我有一个包含100列和100万行的订单表。它在OrderID和FK约束StoreID - > Store.StoreID上有一个PK。上述为什么在MySQL中查询需要很长时间,即使有LIMIT子句?

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列的列吗?

谢谢!

+0

如果你有一个有100列的表格,那么表格的设计就会出错。作为一个经验法则,RDBMS擅长使用细长的表格,只要您可以应用明智的btree索引即可。 – gview

+0

虽然很容易指出不好的设计,但不会简单地从头开始编写所有的东西,或者在获得第一个机会时重新设计/重写。 =) – Xerion

+0

Xerion:事实上,指出一个糟糕的设计并不容易 - 如果是的话,会有更少的糟糕设计。它实际上需要了解关系数据库背后的基本概念,以及有效设计模式的一些经验。然而,我不需要那些人说,当你规定你有一个100列以上的桌子时,那种设计是完全错误的。我知道它可能不是你的设计,你可能无法改变它,但你也被画到了一个角落,在这个角落里,容易和高性能的东西都不是。 – gview

回答

2

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

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;

+0

除了在答案中的可读性/格式化之外,最终的查询正是我所建议的...... – DRapp

+0

酷,这是一个不错的诀窍。 – Xerion

2

你所有的例子都要求现有的表的表扫描,所以没有人会比在何种程度上的MySQL可以缓存数据或结果或多或少的高性能。你的一些查询有顺序或连接标准,它们可以纯粹的利用索引来提高连接过程的效率,但是,这仍然不同于具有一组触发索引使用的标准。

限制不是一个标准 - 一旦确定了结果集,它可以被认为是过滤。一旦结果集准备就绪,您就可以节省客户端上的时间,而不是在服务器上。

真的,让你正在寻找的答案,唯一的办法就是去熟悉: EXPLAIN EXTENDED your_sql_statement

EXPLAIN会告诉你多少行正在看着由MySQL,以及对输出无论是否使用任何索引。

相关问题