表结构:
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行。为什么dt
上的索引未使用?我该如何解决?
答案 0 :(得分:2)
按dt
顺序检索较大的日期范围时,使主键的第一部分dt
会有所帮助:
alter table stat_old
drop key dt,
drop key dt_2,
add primary key (`dt`,`offer_id`,`aff_id`)