背景
1、産品的問題點
- PG 索引無版本資訊
2、問題點背後涉及的技術原理
- PG 的索引沒有TUPLE版本資訊, 是以必須回表才能判斷記錄是否是dead tuple, 是否對目前事務可見.
-
- 為了解決這個問題, PG引入VM file, 記錄每個data block的狀态, 當datablock為clean狀态時, 則不需要回表, 但是也要通路VM才能判斷datablock為clean狀态呀, 是以離散IO次數是沒有節省下來的, 節省的是IO覆寫範圍, 畢竟VM裡面2bit就表示1個data block(預設8KB).
3、這個問題将影響哪些行業以及業務場景
- 對IO敏感的場景
- 多對象的時序、時空場景, 對某個對象, 範圍掃描大量記錄, 需要回表, 産生大量離散IO. 例如查詢某個車輛的軌迹.
4、會導緻什麼問題?
- 即使采用 include index , 葉子節點包含需要查詢的所有資料, 但是如果需要回表判斷, 離散IO依舊是問題(從索引到table或VM檔案都是離散IO).
- 額外對table資料檔案的回訪, 導緻浪費shared buffer.
- 在删除大量資料後 或者 更新大量資料後, 如果索引的垃圾版本未及時進行垃圾回收, 将導緻命中這部分索引的Query性能急劇下降.
5、業務上應該如何避免這個坑
- 盡量不要使用更新, 使得大部分資料塊内的記錄都是對所有會話可見, 是以不需要回表查詢, 減少IO.
- 按對象ID分區, 使用BRIN索引代替BTREE索引, 減少時序類資料的範圍搜尋IO.
6、業務上避免這個坑犧牲了什麼, 會引入什麼新的問題
- 管理複雜度增加
7、資料庫未來産品疊代如何修複這個坑
- 核心層支援索引版本