Postgresql中的點陣圖掃描(bitmap scan)

来源:https://www.cnblogs.com/wy123/archive/2020/07/25/13376991.html
-Advertisement-
Play Games

從MySQL的MRR開始 開始之前,先從MySQL入手,看一下MySQL中的MRR機制原理,也就是Multi-Range Read。MySQL中在按照非聚集索引的範圍查找且需要回表的情況下,比如select * from t where c2>100 and c2<200;c2為非聚集索引。如果直接 ...


 

從MySQL的MRR開始

開始之前,先從MySQL入手,看一下MySQL中的MRR機制原理,也就是Multi-Range Read。
MySQL中在按照非聚集索引的範圍查找且需要回表的情況下,比如select * from t where c2>100 and c2<200;c2為非聚集索引。
如果直接根據非聚集索引(二級索引)鍵中的聚集索引鍵去回表,會產生大量的隨機性IO讀取(圖1)。
為了避免頻繁的回表造成的隨機IO,讀取完非聚集索引上符合條件的key值之後,對key值對應的聚集索引鍵(圖2的rowid)排序,然後根據排序後的聚集索引鍵順序地回表,從而避免大量的隨機性IO。
因為MySQL的Innodb表都是聚集表,那麼圖2中的rowid排序後,是順序性的映射到聚集索引的page,從而避回表過程中的隨機性IO。

(圖1) (圖2)

以上原理清楚後,繼續引申出來另外一個經典的問題:
MySQL中的Innodb總是聚集索引表,或者SqlServer中的聚集表,非聚集索引為什麼要拿聚集索引鍵(而非物理地址)作為其行指針?
對於聚集表,表中數據的物理位置因為需要保證按聚集索引建有序,同時意味著其真正的物理的rowid可能會發生變化(比如聚集索引非線性寫入的時候,會導致葉分裂,頁分裂會導致原始記錄的物理位置變化),此時非聚集索引的行指針rowid也要做修改,這樣會導致聚集表中的數據發生物理位置變化的時候,非聚集索引也要做相應的變化,如果非聚集索引用對應的聚集索引鍵做指針的話,就不會發生該問題。

由以上兩個問題做鋪墊,來看看Postgresql中如何處理類似的問題。

Postgresql中的點陣圖掃描(bitmap scan)

如果遇到類似於上述的查詢(select * from t where c2>100 and c2<200;c2為非聚集索引的)情況下,查詢結果是一個範圍,那麼Postgresql在回表的過程中,如何避免類似於上述圖1中的隨機性IO?
先弄清楚Postgresql的數據存儲特點,Postgresql表的數據都是以堆表(heap)的形式存儲的,因此Postgresql中不存在所謂的聚集索引,同時意味著其記錄在物理結構上可以是無序存儲,不會產生所謂的頁分裂(page split)。
那麼Postgresql中的行指針,這裡稱作rowid,正常情況是不會因為新數據的寫入導致類似於MySQL或者sqlserver中的頁拆分(page split)。
然後再說Postgresql的bitmap scan,bitmap scan的作用就是通過建立點陣圖的方式,將回表過程中對標訪問隨機性IO的轉換為順行性行為,從而減少查詢過程中IO的消耗。
先從一個非常簡單的demo入手,如下查詢,是一個典型的根據非聚集索引且需要回表的查詢,滿足以上的條件。
可以看到在對idx_c5上執行了一個Bitmap Index Scan,由於Bitmap Index Scan記錄的是符合條件的記錄所在的block,而非記錄的指針,然後對這些block排序後再進行回表,Bitmap Index Scan之後有一個Recheck Cond是因為解析block的時候需要Recheck 。
參考這裡:The bitmap is one bit per heap page. The bitmap index scan sets the bits based on the heap page address that the index entry points to.

最後,bitmap scan之後,對錶的訪問,總是通過bitmap Heap Scan完成。也就是執行計劃的第一行。
這裡的bitmap scan與上文中提到的MySQL中的MRR的思路算是一致的,都是通過中間一個緩存來避免隨機性的IO訪問,提升查詢效率。
與基於聚集索引的總是從B+樹的根節點通過二分法查找訪問相比,對於postgresql中的這種直接基於物理Id的訪問,從這一點上看,效率並不一定低。

bitmap scan的訪問優化是基於代價考慮的,對於類似的查詢,不總是一定走bitmap scan,如下,當訪問的數據範圍足夠小的時候,可能不會走bitmap scan。

另外,bitmap scan的優化可以是基於不同欄位或者不同篩選條件的,比如 where a>m and b>n(BitmapAndPath),亦或是where a>x or b>y(BitmapOrPath)這種訪問方式,都可以通過bitmap scan來優化實現。

只不過筆者這裡還有一個問題,因為postgresql中對行的update都是直接刪除原始記錄,然後新寫入一條記錄來實現的,只要這條記錄的物理頁面不變,那麼非聚集索引的行指針就不變,如果這個記錄的物理頁面發生了變話,是不是索引的指針也會發生變化?

相關參數

正常情況下,是否用到bitmap scan優化,postgresql 優化器是可以選擇出來一種最優的方式來執行的,但不保證總是可以生成最優化的執行計劃,可以通過禁用bitmap scan或者 seqscan來嘗試對比和調優。
任何優化都是一個系統工程,而不是一個單點工程,通過不同資源的消耗比例來提升整體性能,bitmap scan也並非完美無瑕,其優化理念是通過bitmap 的生成過程中增加記憶體和CPU欄位消耗來減少IO消耗。
如果是高性能存儲或者有充足的記憶體,並不一定總是發生物理IO,那麼IO並不一定會是瓶頸,相反機械地去做bitmap的生成的話,反倒是一種浪費。
此時可以根據具體的IO能力,比如磁碟的隨機讀和順序讀代價參數,或者是禁用bitm scan等,來做整體上的優化方案。


參考
https://dba.stackexchange.com/questions/119386/understanding-bitmap-heap-scan-and-bitmap-index-scan
https://blog.csdn.net/weixin_33672400/article/details/89734245


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、函數嵌套 1.函數的嵌套調用 在調用一個函數的過程中又調用其他函數 將一個大工能拆解成很多小功能 每個函數名都是全局變數,可以在全局有效 2.函數的嵌套定義 在函數內定義其他函數 子函數只能能在函數中被使用,子函數名只在局部有效 最外層函數相當於一個容器,裝了很多子函數 3.函數的嵌套調用和嵌套 ...
  • 百度網盤:Python項目開發實戰(第2版)PDF高清完整版免費下載 提取碼:exep 內容簡介 本書來自真正的開發現場,是BePROUD公司眾多極客在真實項目中的經驗總結和智慧結晶。作者從Python的環境搭建開始講起,介紹了Web應用的開發方法、項目管理及審查、測試與高效部署、伺服器調試等內容, ...
  • 前言 本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。 作者:彥頁走刀口 今天我們來看看用ghpython怎麼實現koch曲線的分形效果,前兩天分享的雪花分形是利用grasshopper的迴圈插件anemone實現的,然後有個小伙 ...
  • 前言 在朋友的項目有個自定義配置文件user.yml,其內容如下 user: userId: 1 name: 張三 email: [email protected] 其映射實體內容為如下 @Data @AllArgsConstructor @NoArgsConstructor @Builder @Pro ...
  • 在我們開發各種應用的時候,都會碰到很多不同的問題,這些問題涉及架構、模塊組合、界面處理、共同部分抽象等方面,我們這裡以Winform開發為例,從系統模塊化、界面組件選擇、業務模塊場景劃分、界面基類和輔助類處理、代碼生成工具輔助開發等方面介紹在實際項目開發過程中碰到的困境和相關的解決方案,以便分析其中... ...
  • 1、資料庫 根據需要附加或者還原U9對應資料庫; 2、配置IIS ①:打開IIS管理器,在網站預設節點(Default Web Site),添加應用程式; ②:配置應用程式(文件夾必須是非漢字命名); 3、Classview訪問 Classview訪問(部署在本地訪問地址為:http://127.0 ...
  • 通過對 Microsoft.AspNetCore.Cors 的內部實現的剖析,我們瞭解到,其實現 CORS 的原理非常簡單,結構清晰,就算不用系統自帶的 CORS 組件,自行實現一個 CORS 策略,也是非常容易的。 ...
  • 達夢存儲過程的語法與oracle的高度相似,但有好多細節還是有差異。我在這次項目遷移中踩過不少小坑,在這裡給大家分享一下。 說明一下,我用的版本是達夢8,遷移時碰到的問題有些我已經反饋給達夢的官方群管理員,估計以後會有修複。 rpad問題 達夢的rpad函數,計算中文時永遠是認為一個中文字元中兩個字 ...
一周排行
    -Advertisement-
    Play Games
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...
  • 1. JUnit 最佳實踐指南 原文: https://howtodoinjava.com/best-practices/unit-testing-best-practices-junit-reference-guide/ 我假設您瞭解 JUnit 的基礎知識。 如果您沒有基礎知識,請首先閱讀(已針 ...