mysql - 为什么索引不适用于非唯一日期时间列?
问题描述
表结构:
CREATE TABLE `stat_old` (
`dt` datetime NOT NULL,
`offer_id` int(11) DEFAULT NULL,
`aff_id` int(11) DEFAULT NULL,
UNIQUE KEY `dt` (`dt`,`offer_id`,`aff_id`),
KEY `dt_2` (`dt`),
KEY `offer_id` (`offer_id`),
KEY `aff_id` (`aff_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
该dt
字段存储转换为小时的日期时间值,例如“2019-01-01 01:00:00”、“2019-01-01 02:00:00”,并且它不是唯一的。
询问:
explain select *
FROM stat_old
WHERE
dt between '2019-02-11 16:00:00' and '2019-02-18 15:59:59'
order by dt;
结果:
+----+-------------+----------+------+---------------+------+---------+------+----------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+------+---------+------+----------+-----------------------------+
| 1 | SIMPLE | stat_old | ALL | dt,dt_2 | NULL | NULL | NULL | 18914072 | Using where; Using filesort |
+----+-------------+----------+------+---------------+------+---------+------+----------+-----------------------------+
如您所见,它几乎扫描了包含 20,044,835 行的整个表。实际上结果数据只有 2,108,707 行。为什么 index ondt
不使用?我怎样才能解决这个问题 ?
解决方案
当按顺序检索更大的日期范围时,制作dt
主键的第一部分将有所帮助dt
:
alter table stat_old
drop key dt,
drop key dt_2,
add primary key (`dt`,`offer_id`,`aff_id`)
推荐阅读
- java - 如何使用 holder.todoCheckbox.setChecked?回收站视图
- android - 达到 maxLength 后,Android EditText 错误被重置
- tensorflow - ML.PREDICT 的多列输入,用于 BigQueryML 中的 TensorFlow 模型
- c - 反转数组时出现以下错误:二进制*的无效操作数(具有'int'和'int *')
- sql - 为什么我在 pl/sql 的 for 循环中得到这个 group-by 错误?
- java - 接收 null Parcelable 对象 Android
- wpf - 如何在 mvvm 中获取文本块的值
- reactjs - 反应不从 docker 容器发出请求
- swift - SwiftUI:从另一个初始化程序调用它时,如何让我的闭包返回“内容”而不是“某些视图”?
- excel - VBA粘贴剪贴板内容(唯一值)