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

fzsnzjdm  于 2023-02-03  发布在  Mysql
关注(0)|答案(2)|浏览(167)

date/datetime列上的索引没有针对YEAR(col),MONTH(col)函数进行优化,这仍然正确吗?Bill Karwin在这里给出了一个相当明确的答案,但由于这是十年前的问题,我想检查一下。
压缩为YYYY×16×32 + MM×32 + DD的三字节整数
它可以以这样的方式被索引,即它可以以与当执行X1 E0 F1 X时的多列索引相同的方式被优化。
这种优化真的还不存在吗?为什么不可能呢?

fdbelqdn

fdbelqdn1#

正确。一旦WHERE子句中的列被函数 Package ,MySQL优化器就不会使用索引。简单的原因是,一旦您在列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来自动优化此类查询。

mrfwxfqh

mrfwxfqh2#

问题不在于日期的 * 表示 *,而在于查询的优化。当您在日期列上使用YEAR()MONTH()时,该列是参数的函数。
这意味着编译器会有很多关于函数的信息,以便使用索引扫描或索引查找来优化它。

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

当然,这些事情都是可能的,挑战实际上是将它们构建到函数定义和优化器中,构建SQL优化器的人都不会想要为特定函数添加特殊情况(嗯,几乎没有人;SQL Server允许使用cast()来利用索引)。
所以,你的问题的答案是,比尔的答案仍然有效。

相关问题