在MySQL的where子句中,YEAR()和BETWEEN哪个表现更好?

6

我需要从MySQL数据库中查找所有在特定年份创建的记录。以下两种方法,是否有一种比另一种慢?

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

或者

WHERE YEAR(create_date) = '2009'
4个回答

6

This:

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

...由于它不会更改create_date列中的数据,因此DATE(create_date)更好。这意味着如果create_date上有索引,则可以使用该索引--因为索引是基于列中实际存在的值。

不能在YEAR(create_date)上使用索引,因为它仅使用值的一部分(需要提取)。


5
每当您使用一个函数操作一列时,它必须在每一行上执行函数以查看是否匹配常量。这会防止索引的使用。
因此,基本的经验法则是避免在比较的左侧使用函数。
"Sargable"意味着DBMS可以使用索引。将列用作左侧,常量用作右侧,以允许DBMS利用索引。
即使在create_date列上没有索引,DBMS仍然需要为每一行运行YEAR()函数,这会导致额外开销。因此,无论如何,第一种方法很可能更快。

3

我希望前者更快,因为它是sargable


0

思路:

  1. 检查执行计划;如果它们相同,查询性能可能会非常接近。
  2. 在生产级别的机器上对大量测试数据(其大部分行为2009年以外的年份)进行性能测试(确保条件相同,例如冷/热缓存)

但我预计BETWEEN会获胜。除非优化器足够聪明地为YEAR()进行优化,否则结果将是相同的。

另一个想法:

我认为你并不关心。

如果每年仅有少量记录,则即使进行全表扫描,查询也会很快,因为即使有(假设)100年的数据,记录数量也很少。

如果每年有非常多的记录(比如10^8),那么无论如何查询都会非常慢,因为返回那么多记录需要很长时间。

您没有说要保留多少年的数据。我猜如果这是一款考古数据库,您可能只有几千年的数据,如果是这样,您可能会关心是否存在大量数据负载。

我认为在这种情况下,你的应用程序极不可能注意到使用“好”的解释计划(使用索引范围扫描)和“坏”的解释计划(全表扫描)之间的差异。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接