天天看點

【DB吐槽大會】第18期 - PG 索引無版本資訊

背景

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、資料庫未來産品疊代如何修複這個坑

  • 核心層支援索引版本

https://github.com/digoal/blog/blob/master/202109/20210902_06.md#postgresql-%E8%AE%B8%E6%84%BF%E9%93%BE%E6%8E%A5 https://github.com/digoal/blog/issues/76