重要的事情
是否可以确定WHERE
条件的最佳顺序以使其更快?例如,我有一个包含6个条件的查询。一些简单的,其他的子查询或函数。我的想法是对查询进行概要分析,以确定条件true
的常见程度以及运行成本。
阅读示例
例如,我有它:
WHERE
table.ageMin >= :ageFilter AND #1 age-more-than
table.ageMax <= :ageFilter AND #2 age-less-than
YEAR(table.date) >= :dateFilter AND #3 year
(SELECT ...) = TRUE AND #4 first-query
(SELECT ...) = FALSE AND #5 second-query
USER_FUNCTION(table.tag, :tagFilter) #6 user-function
所以,让我们说,在一个月内,我们有:
考虑到(伪ms
值):
所以,我可能会这么想:
#3
将在85%的时间内失败,查询费用仅为0.030毫秒; #2
将在31%的时间内失败,查询费用仅为0.005毫秒; #1
将失败5%,但查询费用仅为0.005毫米; #5
费用超过#4
+ 0.120毫秒,但会在50%的时间内失败; #4
花费0.140毫秒,但只失败了3%; #6
花费0.450毫秒,但只失1%; 所以我的WHERE命令就像:
WHERE
YEAR(table.date) >= :dateFilter AND #3 up, up
table.ageMax <= :ageFilter AND #2 maintained
table.ageMin >= :ageFilter AND #1 down down
(SELECT ...) = FALSE AND #5 up
(SELECT ...) = TRUE AND #4 down
USER_FUNCTION(table.tag, :tagFilter) #6 maintained
因此,如果我在一个月内有1.000.000个查询,那么在第一个例子中,我将会:
因此,在100万个查询中,只有47.210是真的。并且它花了89.436秒来处理所有查询很长一个月。
在对我的WHERE重新排序之后,它将成为:
因此,在100万次查询中,它花费了85.174,比原始订单少了4.262秒。在这个简单的比较中差异是5%,但我有大约50个条件的表(一些复合,其他没有)。我试图修正顺序,查询从0.500ms减少到0.075ms。
但是,这是一项艰苦的工作,逐一检查,并确定哪种更常见,成本更低。那么,有一些工具可以使这项工作吗?
答案 0 :(得分:2)
WHERE
子句中的条件顺序无关紧要。 MySQL查询优化器为查询执行了许多类型的changes,以使其尽可能快地运行。
由于子查询,您的查询速度很慢。优化器可以将某些类型的子查询转换为表连接,这种更改可以大大提高运行速度。
我无法建议对您的子查询进行任何改进,因为您没有提供这些改进。
您可以轻松改进条件YEAR(table.date) >= :dateFilter
的评估。使用函数(YEAR()
)可以防止MySQL使用索引。如果您将其更改为比较table.date
与一年中的第一天(例如,在2015-01-01
中放置2015
而不是dateFilter
),那么MySQL可以使用索引和速度执行。
当然,如果您为该列创建了索引,MySQL会使用索引。确保列date
,ageMin
和ageMax
上有索引。
将EXPLAIN
放在查询前面,并根据EXPLAIN output format
的文档检查结果,找出查询速度慢的原因以及如何改进查询。
答案 1 :(得分:1)
不,mysql中的优化器并不关心where条件的顺序。它使用统计信息(直方图)来确定应用where语句的顺序(AND使用正确的索引:准备好索引)。如果它真的没有目标,你可以使用一个提示并强制使用某个索引,但是你的查询只针对这一个案例进行了优化,这对于其他案例的性能来说真的是有害的
答案 2 :(得分:1)
MySQL的查询计划程序重新排序由WHERE
连接在一起的AND
子句,以提出它所猜测的最佳执行计划。
您不能通过弄乱查询中的子句顺序来影响这一点。
一旦你的桌子大部分被填充,你可以使用ANALYZE TABLE
来影响它。
您可以通过使用与查询中的列匹配的列创建一个或多个复合索引来影响它。读这个。 http://use-the-index-luke.com/
如果您是基准测试内容,请务必在查询开头编写SELECT SQL_NO_CACHE
而不是SELECT
。否则,MySQL将满足来自缓存的重复查询并且显得非常快。
答案 3 :(得分:0)
如果我们订购(可能是提示强制)where条件,以便我们从第一个条件中消除最大行数,如果我们从#6条件开始消除99%的行,其余部分条件仅适用于剩余的1%,依此类推。所以我建议从条件中排序条件,以消除以最少的一行结束的最大行数。