DM 一次SQL優化經歷

2020-09-28 14:00:29

工作中遇到一個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優化成功