使用索引进行日期和时间查找

许多真实世界的数据库表都有很多行,其中 DATETIME 或者 TIMESTAMP 列值跨越很多时间,包括数年甚至数十年。通常需要使用 WHERE 子句来检索该时间跨度的某个子集。例如,我们可能希望从表中检索 2016 年 9 月 1 日的行。

一种效率低下的方法是这样的:

 WHERE DATE(x) = '2016-09-01'   /* slow! */

这是低效的,因为它将函数 - DATE() - 应用于列的值。这意味着 MySQL 必须检查 x 的每个值,并且不能使用索引。

这是一种更好的操作方法

 WHERE x >= '2016-09-01'
   AND x <  '2016-09-01' + INTERVAL 1 DAY

这将选择在当天任何地方的 x 的值范围,直到但不包括 (因此 <)第二天的午夜。

如果表在 x 列上有索引,则数据库服务器可以对索引执行范围扫描。这意味着它可以快速找到 x 的第一个相关值,然后按顺序扫描索引,直到找到最后一个相关值。索引范围扫描比 DATE(x) = '2016-09-01 所需的全表扫描更有效。

不要试图使用它,即使它看起来更有效。

  WHERE x BETWEEN '2016-09-01' AND '2016-09-01' + INTERVAL 1 DAY  /*  wrong! */

它具有与范围扫描相同的效率,但它将选择值为 x 的行,正好在 2016 年 9 月 2 日午夜,这不是你想要的。