繁体   English   中英

DATE 字段和 MONTH() YEAR() 函数上的索引

[英]INDEX on DATE field and MONTH() YEAR() functions

它是否仍然比日期/日期时间列上的索引没有针对 YEAR(col)、MONTH(col) 函数进行优化? Bill Karwin在这里给出了一个非常明确的答案,但因为这是十年前的我想检查一下。 我原以为由于日期列被描述为

一个三字节整数打包为 YYYY×16×32 + MM×32 + DD

它可以以这样一种方式被索引,它可以以与执行紧密索引扫描时多列索引相同的方式进行优化。

这个优化真的不存在吗? 为什么不可能呢?

正确。 一旦 WHERE 子句中的列被函数包裹,MySQL 优化器就不会使用索引。 简单的推理是,一旦您在my_date列上my_date了索引,当您实际寻找不同的值时,例如 YEAR(my_date) 的输出,数据库就没有必要在其中进行搜索。

不过好消息是,在某些情况下有一个快速而简单的解决方案。

例如,可以使用不同的方法优化以下查询:

SELECT flight_company, count(*)
FROM flight_times
WHERE year(FlightDate) = 2017
group by flight_company

不用在 WHERE 子句中使用 YEAR() 函数,您可以只用一个范围条件替换函数调用,该条件将检查相同的事情:

SELECT flight_company, count(*) 
FROM flight_times
WHERE FlightDate between '2017-01-01'
and '2017-12-31'
GROUP BY flight_company

虽然有些函数不能简单地替换为范围条件,例如在 YEAR 的情况下。 例如,您将如何用条件替换 dayofweek() ? 恐怕更难。 因此,另一种方法是使用 MySQL 5.7 Virtual (generated) columns 如果你采用这种方法,你可以在你的 CREATE TABLE 语句中创建这个虚拟列,以实际匹配 dayofweek() 的结果:

Flight_dayofweek tinyint(4)
 GENERATED ALWAYS AS (dayofweek(FlightDate
 VIRTUAL

作为EverSQL的联合创始人,我虚心建议您使用EverSQL SQL Query Optimizer来自动优化此类查询。

问题不在于日期的表示 问题是查询的优化。 在日期列上使用YEAR()MONTH()时,该列是参数的函数。

这意味着编译器将拥有大量有关该函数的信息,以便使用索引扫描或索引查找对其进行优化。 比如:

  • 给定相同的参数,该函数必须返回相同的值。
  • 该函数将只接受一个参数。
  • 该函数需要是单调的。
  • 该函数需要有一个反函数(用于启动索引扫描)。

当然,这些都是可能的。 挑战实际上是将它们构建到函数定义和优化器中。 构建 SQL 优化器的人都不想为特定函数添加特殊情况(好吧,几乎没有人;SQL Server 确实允许使用cast()来利用索引)。

所以,你的问题的答案是比尔的答案仍然有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM