工作中遇到一个SQL查询慢的问题
查询语句是:
SELECt * FROM db_msg.t_xxpt_xx_cocall xx WHERe dt_fssj >=‘2020-06-03 00:00:00’ AND dt_fssj <= ‘2020-06-10 23:59:59’ order by dt_fssj desc limit 20;
筛选字段为30w左右数据,返回结果集20,首次执行时会执行有7,8秒的时间
为了优化这个SQL我首先查看这个SQL执行计划:
1 #NSET2: [6696, 20, 764]
2 #PRJT2: [6696, 20, 764]; exp_num(26), is_atom(FALSE)
3 #SORT3: [6696, 20, 764]; key_num(1), is_distinct(FALSE), top_flag(1), is_adaptive(0)
4 #BLKUP2: [418, 198120, 764]; I_XXPT_XX_COCALL_FSSJ(XX)
5 #SSEK2: [418, 198120, 764]; scan_type(ASC), I_XXPT_XX_COCALL_FSSJ(T_XXPT_XX_COCALL as XX), scan_range[exp_cast(‘2020-06-03 00:00:00’),exp_cast(‘2020-06-10 23:59:59’)]
执行计划时首先走SEEK2二级索引数据定位,同时筛选字段数据,然后走BLKUP2(定位查找)
然后我这边打开MONITOR_SQL_EXEC参数,然后执行这个语句,使用ET来查看这个执行计划每个步骤的消耗,发现执行计划BLKUP2这一步会消耗百分之98以上时间。
主要是因为当前语句为select * 要返回所有列的信息,而二级索引只记录rowid和索引列信息,所以执行计划需要定位查找其他列数据,消耗大量资源
所以后续优化中去掉了此列上的普通二级索引,新建了一个聚集索引,聚集索引上包含所有列的值,走CSEK2查找筛选后就能获得所有列的值,不会再走BLKUP2(定位查找)这个过程,从而减少资源开销
添加聚集索引:
CREATE CLUSTER INDEX I_XXPT_XX_COCALL_FSSJ ON db_msg.t_xxpt_xx_cocall (DT_FSSJ DESC);
然后查看新的执行计划:
1 #NSET2: [0, 20, 764]
2 #PRJT2: [0, 20, 764]; exp_num(26), is_atom(FALSE)
3 #TOPN2: [0, 20, 764]; top_num(20)
4 #CSEK2: [0, 100, 764]; scan_type(ASC), I_XXPT_XX_COCALL_FSSJ(T_XXPT_XX_COCALL as XX), scan_range[exp_cast(‘2020-07-10 23:59:59’),exp_cast(‘2020-07-03 00:00:00’)]
新计划下执行时间基本不到1S,SQL优化成功