1. 程式人生 > 實用技巧 >PG優化實戰系列-200+s到毫秒級記錄?

PG優化實戰系列-200+s到毫秒級記錄?

背景  

  前段時間同事在優化一個SQL,優化效果從最開始的200+s通過SQL改寫優化到20s,但是依舊不能滿足現場需求,於是發給我們瞅瞅。

問題解決

表情況

tab1是一張大表,一年資料量億級別,已經按年分割槽存在索引 idx1(time1,colx),id唯一

原始SQL:

select count(*) from(
select id from tab1 where time1 between 1511745973 and 1606440373 and col1 = 'xx1'
union
select id from tab1 where time1 between 1511745973 and
1606440373 and col2 = 'xx2' union select id from tab1 where time1 between 1511745973 and 1606440373 and col3 = 'xx3') tmp;

以上SQL是取3年的資料,可以看到資料量非常大,此時已經失去分割槽表的作用了,就算走idx1索引效果可能會更差。

優化思路

考慮colx的過濾性,在time1過濾性差的情況下,應該考慮執行計劃優先走colx的索引然後再對時間進行過濾。

create index idx_tab1_col1_time1 on tab1(col1,time1);
create
index idx_tab1_col2_time1 on tab1(col2,time1); create index idx_tab1_col3_time1 on tab1(col3,time1);

SQL改寫:id欄位沒有重複值,可以去掉沒必要的union

select count(*) from tab1 where (col1 = 'xx1' or col2 = 'xx2' or col3 = 'xx3') and time1 between 1511745973 and 1606440373;

重新執行耗時變成毫秒級別(具體多少忘了。。)

問題總結:

1.分割槽適合查詢時只對部分分割槽欄位進行過濾的查詢,對於比如人員資訊表這些將失去意義,總而言之就是分割槽就是為了減少對資料的掃描,適合對資料週期性淘汰。
2.多列索引的順序直接決定所建索引是否合適,建議過濾性好的做前導列,多列索引如(id1,id2,id3)能用於(id1),(id1,id2),(id1,id2,id3)的查詢 3.PG支援OR條件用組合索引(bitmapscan or4.儘量避免排序(改寫union,distinct等)