为什么mysql在使用日期函数进行换行时命中索引

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么mysql在使用日期函数进行换行时命中索引相关的知识,希望对你有一定的参考价值。

IMO,当add_time字段用date()func换行时,下面的mysql不会命中索引,但是从解释结果来看,它命中索引,为什么?

explain 
SELECT count(0) 
FROM xxx 
WHERE  date(add_time) >= date_sub(curdate(), INTERVAL 7 day);

enter image description here

答案

众所周知,EXPLAIN报告难以解释。他们将过多的信息过载到了几个领域。你可以试试

type: index表示它正在进行索引扫描,这意味着它正在访问索引中的每个条目。

这会访问与表扫描相同数量的条目,除了它是针对辅助索引而不是聚簇(主)索引。

当我们看到type: index时,EXPLAIN显示possible_keys: NULL,这意味着它无法使用任何索引进行有效搜索。但它也显示了key: add_time,这意味着它用于索引扫描的索引是add_time

索引扫描是由于MySQL无法自行优化表达式或函数调用。例如,如果您尝试搜索特定月份的日期,则可以搜索month(add_time) = 4但不会在add_time上使用索引,因为该月份的日期分散在索引中,而不是全部组合在一起。

你可能知道date(add_time)应该可以通过索引进行搜索,但是MySQL并没有做出推断。 MySQL只是看到你正在使用一个函数,它甚至没有尝试使用索引。

这就是为什么MySQL 5.7引入generated columns以允许我们索引表达式,而MySQL 8.0通过允许index to defined for an expression使其更好,而不需要我们首先定义生成的列。

另一答案

我想你可能在这里误解了解释计划。如果你看下possible_keys,你会发现它是NULL。从MySQL documentation上解释输出格式:

如果此列为NULL(或在JSON格式的输出中未定义),则没有相关索引。

因此,Extra部分中提到的正在使用的索引可能与add_time无关。

以上是关于为什么mysql在使用日期函数进行换行时命中索引的主要内容,如果未能解决你的问题,请参考以下文章

使用日期时间索引在 Python 中进行时间序列预测

mysql无法命中索引的情况

在 div 中换行时出错

mysql索引命中规则

MySQL命中索引代码实验案例

MySQL命中索引代码实验案例