[英]INDEX on DATE field and MONTH() YEAR() functions
正确。 一旦 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.