Postgresql

點陣圖堆掃描作為嵌套循環下的內部節點是如何工作的?

  • July 17, 2022

我大體上理解Bitmap Index Scan其次是如何Bitmap Heap Scan工作的。

但是,我不確定當 aBitmap Heap Scan被選為 a 的內部節點時它是如何工作的Nested Loop

Nested Loop  (cost=86.73..369.99 rows=1 width=37) (actual time=8.487..1823.876 rows=1800 loops=1)
  ->  Bitmap Heap Scan on workspace_history_sets  (cost=11.69..141.51 rows=3 width=32) (actual time=6.046..14.218 rows=636 loops=1)
        Recheck Cond: (workspace_uid = '+++'::uuid)
        Filter: (((project_uid)::character varying)::text = '---'::text)
        Heap Blocks: exact=7
        ->  Bitmap Index Scan on workspace_history_set_idx_workspace_history_set  (cost=0.00..11.69 rows=641 width=0) (actual time=0.198..0.198 rows=636 loops=1)
              Index Cond: (workspace_uid = '+++'::uuid)
  ->  Bitmap Heap Scan on sheets  (cost=75.03..76.15 rows=1 width=90) (actual time=2.818..2.836 rows=3 loops=636)
        Recheck Cond: ((history_set_uid = workspace_history_sets.history_set_uid) AND (project_uid = '---'))
        Heap Blocks: exact=1800
        ->  BitmapAnd  (cost=75.03..75.03 rows=1 width=0) (actual time=2.752..2.752 rows=0 loops=636)
              ->  Bitmap Index Scan on sheets_idx_history_set_uid  (cost=0.00..8.00 rows=551 width=0) (actual time=0.041..0.041 rows=3 loops=636)
                    Index Cond: (history_set_uid = workspace_history_sets.history_set_uid)
              ->  Bitmap Index Scan on sheets_idx_project_uid  (cost=0.00..66.39 rows=1573 width=0) (actual time=2.645..2.645 rows=4612 loops=636)
                    Index Cond: (project_uid = '---')

EXPLAIN上面,我們可以看到Bitmap Heap Scan執行了 636 次(loops=636)

  1. 我是否正確地說每次執行時Bitmap Heap Scan它的子節點僅從外部節點檢索到 1 個鍵(索引)?
  2. 如果上述情況屬實,那麼Bitmap Heap Scan每個循環的統計數據及其子項不是不同的嗎?那麼這些節點中顯示的數字(actual time=2.818..2.836 rows=3 loops=636)是什麼意思?它們是所有循環的平均值嗎?

是的,對 sheet_idx_history_set_uid 的點陣圖索引掃描對每 636 個找到的 workspace_history_sets.history_set_uid 值進行一次。報告的實際時間和行數是平均值。

sheet_idx_project_uid 上的點陣圖索引掃描只是重複了 636 次,因為它沒有從外部引用任何值。它可以只執行一次掃描並每次重用點陣圖,但沒有人實施過這種優化。不幸的是,這是您的查詢花費的主要時間。

如果計劃者有更準確的統計數據,它可能只是掃描 sheet_idx_history_set_uid 作為正常索引掃描,然後project_uid = '---'作為過濾器進行測試。將 BitmapAnd 用於 551 行似乎比將其用於 3 行更合理。你所有的其他統計數據似乎也很不穩定,你應該對這兩個表進行 VACUUM ANALYZE 以查看這是否會改變事情。

多列索引(history_set_uid, project_uid)應該提供更好的計劃,這也將更能抵抗不良統計數據的影響。

引用自:https://dba.stackexchange.com/questions/314510