在SQL中,WHERE子句顺序是否有任何影响?

时间:2011-05-12 16:25:33

标签: mysql sql where-clause

我的数据库中有一个像这样的表:

 ----------------------------------------------------------
| event_id | date       | start_time | end_time | duration |
 ----------------------------------------------------------
| 1        | 2011-05-13 | 01:00:00   | 04:00:00 | 10800    |
| 2        | 2011-05-12 | 17:00:00   | 01:00:00 | 28800    |
| 3        | 2011-05-11 | 11:00:00   | 14:00:00 | 10800    |
 ----------------------------------------------------------

此样本数据无法提供完全准确的图片,通常会有每天每小时发生的事件。 日期始终指的是start_time,因为end_time有时可能是第二天。 持续时间以秒为单位。

SELECT *
FROM event_schedules
WHERE (
       date = CURDATE() //today
       OR
       date = DATE_SUB(CURDATE(), INTERVAL 1 DAY) //yesterday
      )
  // and ended before now()
  AND DATE_ADD(CONCAT(date, ' ', start_time), INTERVAL duration SECOND) < NOW()
ORDER BY CONCAT(date, ' ', start_time) DESC
LIMIT 1

我有一个条款,括号中的OR'ed子句,这是不必要的。我希望它可以通过首先过滤掉今天或昨天没有开始的任何“事件”来改善查询时间。找到最新“事件”的唯一方法是订购记录并取得第一个。通过添加这个额外的不必要的条款我实际上减少了需要订购的记录列表?如果确实如此,我无法想象优化器能够进行这种优化,大多数其他类似的问题都与优化器有关。

3 个答案:

答案 0 :(得分:2)

在为WHERE子句添加过滤器以提高性能时要小心。虽然它可以减少需要搜索的行的总数,但实际的过滤器本身如果过滤大量记录而不使用索引则会导致更高的成本。在您的情况下,如果列日期被索引,您可能会获得更好的性能,因为它可以使用OR部分中的索引,因为它在其他部分中不能,因为它被称为函数。另外,你有未来约会吗?如果没有,为什么不将OR更改为

date > DATE_SUB(CURDATE(), INTERVAL 1 DAY)

答案 1 :(得分:1)

where子句的顺序确实会影响sql引擎获取结果的方式。

他们中的许多人都有办法查看引擎对查询的作用。如果您正在使用sqlserver,请在您的客户端工具中查找“显示估计的执行计划”。有些人有一个像“explain”这样的动词,可用于显示引擎如何处理查询。

答案 2 :(得分:1)

好吧,查询引擎中的优化器是任何查询性能的重要组成部分,或两个等效语句的相对性能。

您没有告诉我们您是否使用额外的地方运行查询。可能存在性能差异,可能没有。

我的猜测是LIMIT与它有很大关系。引擎知道这是一个“完成”操作。如果没有WHERE,排序是一个NlogN操作,在这种特殊情况下,可以通过简单的日期扫描来找到最新的。

使用WHERE,您实际上增加了必须执行的步骤数;要么必须完全对表进行排序(NlogN),然后扫描该列表以查找与WHERE子句匹配的第一条记录(线性最坏情况,常量最佳情况),或者必须按WHERE(线性)进行过滤,然后再次扫描这些记录以找到最大日期(再次线性)。无论哪一个更快,它们都比最近日期列表的一次线性扫描慢。