MySQL BETWEEN 两个日期时间不使用 INDEX
Posted
技术标签:
【中文标题】MySQL BETWEEN 两个日期时间不使用 INDEX【英文标题】:MySQL BETWEEN two datetimes does not use INDEX 【发布时间】:2014-02-24 15:52:21 【问题描述】:explain
SELECT COUNT(*) AS Count, CreatedBy
FROM `Notes`
INNER JOIN Users ON UserID = CreatedBy
INNER JOIN UserRoles ON URoleID = RoleID AND RoleID = 1
WHERE NoteVisible = 1 AND NoteText NOT LIKE '%SOME KEYWORD%'
AND Created BETWEEN '2014-02-24 00:00:00' AND '2014-02-24 23:59:59'
GROUP BY CreatedBy
如您所见,ref 为 NULL,并且经过 23 行,而不仅仅是经过 1 行。现在对于这个例子来说这很快,但是当我做 1-2 个月的范围时,行变成 >10000 并且它减慢了页面并锁定了表格。
注意如果我删除 00:00:00 和 23:59:59 然后它使用索引它只经过 1 行但我需要选择从 00:00 开始到 23:59 结束的一整天的所有数据。
请帮助我重组此查询以解决此问题或提出任何可能的解决方案。谢谢。
编辑
将 BETWEEN 替换为 或 > 或 或 >=没有解决问题
【问题讨论】:
如果用BETWEEN
代替('2014-02-24' <= Created AND Created < '2014-02-25')
会怎样?
已经在不同的变体中这样做了仍然不使用索引
请贴出表的结构,或者至少给查询中的列名加上前缀,很难猜出哪个列属于哪个表。 NoteVisible
是否属于 Notes
?
是 NoteVisible 属于笔记,为什么它会属于任何呈现的表格?
【参考方案1】:
此查询使用索引。
选择类型为range
,使用的键为Created
对于范围类型,ref
列始终为空,
参考文档:http://dev.mysql.com/doc/refman/5.7/en/explain-output.html#jointype_range
范围
仅检索给定范围内的行,使用索引选择行。输出行中的键列指示使用了哪个索引。 key_len 包含已使用的最长密钥部分。 此类型的 ref 列为 NULL。
(强调我的)
【讨论】:
但如果我删除说明它只返回 1 行,则该范围内没有 23 行。 这只是一个估计——MySql 认为有 23 行。它不会在解析阶段检查确切的行数,它只是估计。但考虑到这一点,它认为使用该索引并连接 23 行比使用主键连接 X 行更好。 有没有办法解决减速问题?【参考方案2】:当您在大于/小于比较中将日期时间字段与字符串进行比较时。如果您使用强制转换或函数(如 UNIX_TIMESTAMP())并将其他日期转换为 unixtimestamp,则可以解决问题,但会破坏索引的使用。也许更好的解决方案是将日期作为unix时间戳存储在表中并在其上放置索引。
另一种方式,你可以在你的 sql 中添加“限制”也对我有用
【讨论】:
以上是关于MySQL BETWEEN 两个日期时间不使用 INDEX的主要内容,如果未能解决你的问题,请参考以下文章
使用 mySQL 运算符 BETWEEN 和经典日期间隔之间有啥区别? [复制]