近期在做一个报表监控的项目,主要的查询条件就是时间,每天导入数据库的数据大概几万条,页面的查询范围最多限制在1个月,算下来1个月的数据量最多有300w,功能开发完后自己做了100多万的测试数据,并在作为查询条件的时间字段上加了索引,但是测试时发现并不是每次用时间范围查询的时候都会走索引。
表结构:
CREATE TABLE vehicle_revision_redelivered
(
id
bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
thermosphere
varchar(45) DEFAULT NULL COMMENT '温层',
order_submit_time
datetime DEFAULT NULL COMMENT '下单时间',
collect_service
varchar(45) DEFAULT NULL COMMENT '揽收服务',
delivery_service
varchar(45) DEFAULT NULL COMMENT '派送服务',
expect_pickup_start_time
datetime DEFAULT NULL COMMENT '预计揽件起始时间',
expect_pickup_end_time
datetime DEFAULT NULL COMMENT '预计揽件结束时间',
expect_delivered_time
datetime DEFAULT NULL COMMENT '应妥投时间时间',
sys_redelivered_time
datetime DEFAULT NULL COMMENT '系统操作再投时间',
create_time
datetime DEFAULT NULL COMMENT '创建时间',
create_pin
varchar(45) DEFAULT NULL COMMENT '创建人账号',
PRIMARY KEY (id
),
KEY idx_expect_delivered_time
(expect_delivered_time
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
测试数据量:1151136 条数据
查询语句SQL1:
explain
SELECT create_time
FROM vehicle_revision_redelivered
where expect_delivered_time >= '2019-10-15 00:00:00' and expect_delivered_time<= '2019-10-30 23:59:59' ;
打印结果 Result1:
查询语句SQL2:
explain
SELECT create_time
FROM vehicle_revision_redelivered
where expect_delivered_time >= '2019-11-21 00:00:00' and expect_delivered_time<= '2020-01-30 23:59:59' ;
打印结果 Result2:
同样的sql 不同的只是查询范围不同 第一走的全表扫描,第二个走的索引
分析了一下,总数据量一共是1151136 条 ,10月15至10月30号数据量是290644条 占总数量的25.2% ,扫描行数1004564,11月21号至2020年1月30号数据量是106967,约占总数量的9.3% 扫描行数401360行, 数据主要集中在10月22至11月30号 ,这段时间的数据一共1091903条
查询语句SQL3:
explain
SELECT create_time
FROM vehicle_revision_redelivered
where expect_delivered_time >= '2019-11-20 00:00:00' and expect_delivered_time<= '2020-01-30 23:59:59' ;
查询结果Result3:
11月20至1月30号的数据一共142514 占总数据量的12.3%,扫描行数1004564
查询语句SQL4:
explain
SELECT create_time
FROM vehicle_revision_redelivered
where expect_delivered_time >= '2019-11-20 00:00:00' and expect_delivered_time<= '2020-01-23 23:59:59' ;
查询结果Result4:
11月20号至1月23号的数据一共135789条 约占总数据量的 11.8%,扫描行数426220行
当使用MySql 非主键索引进行查询时 如果扫描数据量接近全表数据量时,mysql会进行全表扫描不会使用索引(主键索引除外),这也是为什么不建议在区分度低的字段
上建索引,也会导致全表扫描。
rows不能直接理解为扫描行数, 表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数也就是mysql认为必须要逐行去检查和判断的记录的条数,实际是mysql根据估算的所需读取的行数决定是全表扫描还是使用索引
网友评论