日期时间字段上的 MySQL 索引不是 RANGE 类型,而是使用 INDEX 类型
Posted
技术标签:
【中文标题】日期时间字段上的 MySQL 索引不是 RANGE 类型,而是使用 INDEX 类型【英文标题】:MySQL index on datetime field not going RANGE type, instead is using INDEX type 【发布时间】:2020-04-23 13:44:24 【问题描述】:我想知道为什么RANGE
类型中没有使用这个索引,而是INDEX
:
索引:
CREATE INDEX myindex ON orders(order_date);
查询:
EXPLAIN
SELECT order_date FROM orders
WHERE order_date BETWEEN '2020-01-01 00:00:00' AND '2020-12-31 23:59:59';
在输出中,TYPE
列设置为 INDEX
。在我看来,它应该在索引中找到日期大于第一个的记录,然后通过链表,但如果是这种情况,类型应该是range
,而不是INDEX
。
另外,同样在from
子句上使用force index(report_ordini_per_utente_in_un_periodo)
,类型还是index
我正在使用 MariaBD 10.1.43
【问题讨论】:
我的 mysql 5.7 和 MadiaDB 10.1 都有“范围”。能否提供 show create table 输出? 只是一个日期时间字段 您的意思是表中只有一个日期时间列? @fifonik 是的,“order_date”只是一个日期时间,请查看我自己的答案并尝试检查您的版本中是否也有这种行为 对我来说,索引时日期时间不是范围是合乎逻辑的,因为它不是唯一索引。假设你有 3 个日期相似(在这种情况下它是范围的右边缘),那么从这 3 个中,你认为哪一个是实际数据范围的边缘?你不能说。 【参考方案1】:您提供的查询只有一列。该列在索引中。所以,索引是“覆盖”的。因此EXPLAIN
会说Using index
。
表格中的日期范围是多少?
如需进一步讨论,请提供SHOW CREATE TABLE
和所有EXPLAIN
输出。你的散文中可能会遗漏一些微妙的东西。
【讨论】:
好吧,我认为该表的列数并不相关,但是,mariadb 似乎选择使用整个索引,因为没有那么多记录,所以可能更容易扫描整个索引,而不是使用二进制搜索来查找第一个(但是日期分布在整个 2019 年) 列数有很大的不同。只有一列——与ORDER BY
列相同——查询可以完全在索引的BTree 中运行。如果在SELECT
中添加另一列,查询计划会发生变化,查询会运行得更慢。
@AlbertoSinigaglia - 查找第一个数据的“向下钻取”是整个查询中相对微不足道的部分。您说日期分布在 2019,但查询只要求 2020。我正在寻找是否涉及很多行,或者可能没有。
好吧,假设他们是在 2020 年,我这边运行的查询是搜索记录的年份【参考方案2】:
原来是一种错误,因为我在数据库中的所有记录都在该范围内,因此它显然必须遍历整个索引,这就是为什么它将 TYPE
标记为 @987654322 @ 而不是 RANGE
。更奇怪的是,假设查询有order_date between X and Y
,如果所有记录的日期都大于X,但并非所有记录的日期都小于Y,它也将其标记为INDEX
而不是RANGE
【讨论】:
猜测:从头开始可能会有所不同。以上是关于日期时间字段上的 MySQL 索引不是 RANGE 类型,而是使用 INDEX 类型的主要内容,如果未能解决你的问题,请参考以下文章
MySQL 优化器之Index merge Multi-Range Read MRR与Batched Key Access使用案例详解