您好,登錄后才能下訂單哦!
本節介紹了PostgreSQL中數據表的三種掃描類型,分別是順序掃描SeqScan、索引掃描IndexScan和位圖堆掃描BitmapHeapScan。
選擇率=條件過濾后的元組數/條件過濾前的元組數
順序掃描SeqScan
直接對數據表堆數據(Heap Data)進行順序掃描,適用于選擇率較高的場景.
索引掃描IndexScan
通過訪問索引獲得元組位置指針后再訪問堆數據,適用于選擇率較低的場景.
位圖堆掃描BitmapHeapScan
位圖堆掃描需要首先通過BitmapIndexScan(位圖索引掃描)把符合條件的元組所在的Page(Block) ID存儲在Bitmap中,然后再通過Bitmap訪問堆數據,適用于選擇率不高不低的場景,介于上面兩種掃描方式之間.
2018.10.01 修正,索引適用于選擇率低的情況,順序掃描適用于選擇率高的情況
值得注意的地方:
1."選擇率較高"是一種定性的表述,實際上PG是根據Cost計算來確定使用哪種掃描方式.通常情況下,索引掃描主要執行的操作是隨機訪問存儲設備,在PG的初始化參數配置中,隨機訪問的Cost是4,而順序訪問的Cost是1,很粗略的估算,如果通過索引訪問的Index Blocks + Heap Blocks超過順序訪問的Heap Blocks的1/4,那么PG會選擇使用順序掃描而不是索引掃描.
2.IndexScan的掃描方式是訪問索引,如符合條件則馬上根據索引中的元組位置指針訪問堆數據從而獲取元組,而BitmapIndexScan(位圖索引掃描)是訪問索引,把符合條件的Block ID存儲在Bitmap中,這時候不涉及掃描堆數據,最終獲取元組的操作通過BitmapHeapScan掃描完成.
這兩者的不同,下面這段話總結得非常到位:
A plain Index Scan fetches one tuple-pointer at a time from the index, and immediately visits that tuple in the table. A bitmap scan fetches all the tuple-pointers from the index in one go, sorts them using an in-memory "bitmap" data structure, and then visits the table tuples in physical tuple-location order.
下面通過樣例腳本直觀感受這幾種方式的不同.
測試數據表,t_dwxx,10000行數據,在dwbh上創建PK
testdb=# select count(*) from t_dwxx;
count
-------
10000
(1 row)
測試腳本:
testdb=# explain verbose select t1.* from t_dwxx t1 where dwbh > '1000';
QUERY PLAN
----------------------------------------------------------------------
Seq Scan on public.t_dwxx t1 (cost=0.00..189.00 rows=9999 width=20)
Output: dwmc, dwbh, dwdz
Filter: ((t1.dwbh)::text > '1000'::text)
(3 rows)
查詢條件為dwbh > '1000',選擇率較低,PG選擇了順序掃描SeqScan,成本189.00,該成本如何計算,有興趣的可參照源碼解讀(53),通過gdb跟蹤分析.
測試腳本:
testdb=# explain verbose select t1.* from t_dwxx t1 where dwbh = '10000';
QUERY PLAN
-------------------------------------------------------------------------------------
Index Scan using t_dwxx_pkey on public.t_dwxx t1 (cost=0.29..8.30 rows=1 width=20)
Output: dwmc, dwbh, dwdz
Index Cond: ((t1.dwbh)::text = '10000'::text)
(3 rows)
查詢條件為dwbh = '10000',選擇率很高,只有1條記錄,選擇索引掃描.
總成本8.30=啟動成本 + 一次Index Block訪問 + 一次Heap Block訪問=0.29 + 4 + 4≈8.30
測試腳本:
testdb=# explain verbose select t1.* from t_dwxx t1 where dwbh > '1000' and dwbh < '3000';
QUERY PLAN
---------------------------------------------------------------------------------------------
Bitmap Heap Scan on public.t_dwxx t1 (cost=51.07..148.42 rows=2223 width=20)
Output: dwmc, dwbh, dwdz
Recheck Cond: (((t1.dwbh)::text > '1000'::text) AND ((t1.dwbh)::text < '3000'::text))
-> Bitmap Index Scan on t_dwxx_pkey (cost=0.00..50.52 rows=2223 width=0)
Index Cond: (((t1.dwbh)::text > '1000'::text) AND ((t1.dwbh)::text < '3000'::text))
(5 rows)
查詢條件為dwbh > '1000' and dwbh < '3000',選擇率不高不低,PG選擇了BitmapHeapScan,啟動成本為51.07,總成本為148.42,該成本如何計算,后續的源碼解讀會跟蹤分析.
值得注意的是在BitmapIndexScan后有一步:Recheck,這是因為位圖索引掃描只是把Heap Block ID找出來,并沒有把符合條件的元組找出來,因此出現了Recheck這一步.
PostgreSQL indexing: Index scan vs. Bitmap scan vs. Sequential scan
Bitmap indexes
What is a “Bitmap heap scan” in a query plan?
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。