记一次深度分页查询带来的问题

65 阅读2分钟

1、背景:

在告警记录模块有一个告警记录查询,在开发时是做了分页查询展示的,但是,随着告警记录表中的数据增多,在产品经理的一次查询中,结果没有查出来,同时也影响到了正常业务进行,在钉钉推送的告警中也提示说线上MySQL的CPU飙升。

2、定位:

通过钉钉告警记录以及与产品经理询问操作,定位发现是类似如下一条SQL引起的:

select * from t_error_trace where  date > xxx limit 1500000, 10;

其中date字段上有索引,显然会命中索引,但是有个明显的问题是会发生大面积的回表操作,导致SQL执行极慢,再具体一点就是date字段的索引是一个二级索引,它的叶子节点存储的是主键ID,所以会根据主键ID去主键索引上再次查询,这就是回表过程,会扫描1500010条数据,然后丢弃掉前1500000条数据。

3、解决:

既然问题的原因是因为发生了大面积的回表操作,那么可以从减少回表次数来解决,如下:

3.1、方式一:

select * from t_error_trace where id in (select id from t_error_trace where date > xxx limit 1500000, 10);

在子查询中,通过二级索引可以直接定位到对应的主键ID,那么自然需要回表的数据就只有10条了

3.2、方式二:

由于告警记录表是只增不减的,且主键ID自增,那么可以有如下方式:

select * from t_error_trace where date > xxx and id > 1500000 limit 10;