哪个在MySQL where子句中表现更好:YEAR()vs BETWEEN?

时间:2010-10-12 19:54:40

标签: mysql performance

我需要从MySQL数据库中查找给定年份中创建的所有记录。有没有办法让下列其中一个比另一个慢?

WHERE create_date BETWEEN '2009-01-01 00:00:00' AND '2009-12-31 23:59:59'

WHERE YEAR(create_date) = '2009'

4 个答案:

答案 0 :(得分:5)

此:

WHERE create_date BETWEEN '2009-01-01 00:00:00' AND '2009-12-31 23:59:59'

...效果更好,因为它不会改变create_date列中的数据。这意味着如果create_date上有索引,则可以使用索引 - 因为索引位于列中存在的实际值上。

YEAR(create_date)上无法使用索引 ,因为它只使用了值的一部分(需要提取)。

答案 1 :(得分:4)

每当对列使用函数时,它必须在每一行上执行该函数,以查看它是否与常量匹配。这可以防止使用索引。

基本的经验法则是避免使用比较左侧的函数。

Sargable意味着DBMS可以使用索引。使用左侧的列和右侧的常量以允许DBMS使用索引。

即使您在create_date列上没有索引,DBMS仍然会为每行运行YEAR()函数。所以,无论如何,第一种方法最有可能更快。

答案 2 :(得分:3)

我希望前者更快,因为sargable

答案 3 :(得分:0)

思路:

  1. 检查解释计划;如果它们相同,查询性能可能几乎相同。
  2. 在生产级机器上测试大量测试数据(其中大部分行数为2009年以外的其他行)的性能(确保条件相同,例如冷/热缓存)
  3. 但我希望BETWEEN获胜。除非优化器足够聪明地对YEAR()进行优化,否则在这种情况下会相同。

    另一个想法:

    我认为你不在乎。

    如果你每年只有几条记录,那么即使进行全表扫描,查询也会很快,因为即使有(比方说)100年的数据,记录也很少。

    如果你每年有大量的记录(比如10 ^ 8)那么查询在任何情况下都会非常慢,因为返回那么多记录需要很长时间。

    您没有说明您保留了多少年的数据。我想如果它是一个考古数据库,你可能有几千个,在这种情况下你可能会关心你是否有大量的数据。

    我发现你的应用程序实际上不太可能注意到“好”解释计划(使用索引范围扫描)和“坏”解释计划(全表扫描)之间的区别。