1. 統計信息收集
PostgreSQL 依賴于表和索引的統計信息來估算選擇率。這些統計信息在以下情況下收集:
- ANALYZE 命令:手動運行 ANALYZE 命令來更新統計信息。
- 自動分析:PostgreSQL 會根據表的修改頻率自動更新統計信息。
統計信息包括:
- 行數(tuples):表中總行數。
- 列的基數(distinct values):列中不同值的數量。
- 最小值和最大值:列中的最小和最大值。
- NULL 值的數量:列中 NULL 值的數量。
2. 選擇率計算
選擇率的計算通常基于以下公式:Selectivity=符合條件的行數\總行數
選擇率的計算通常考慮以下因素:
- 單列條件:對于單列的條件,如等值查詢(=),選擇率可以通過基數和總行數來估算;對于范圍查詢(<, >, BETWEEN),則需要考慮值的分布。
- 多列條件:對于多列條件,例如 WHERE column1 = value1 AND column2 = value2,選擇率的估算可能更復雜。優化器會考慮列之間的相關性(即列值之間的統計關系),并使用乘法法則來估算。
3. 復雜條件
對于復雜的查詢條件(如AND、OR組合),PostgreSQL會使用以下策略:
- AND條件:選擇率通常為各條件選擇率的乘積。
- OR條件:選擇率通常為各條件選擇率的和,但需要考慮重疊部分。
4. 使用的函數
PostgreSQL使用一系列內置函數來幫助估算選擇率,包括:
- eqsel:用于等值條件的選擇率估算。
- ltsel、gtel:用于小于、大于條件的選擇率估算。
- andselectivity、orselectivity:用于組合條件的選擇率估算。
5. 使用直方圖和其他統計信息
為了提高選擇率估算的準確性,PostgreSQL 還使用直方圖(histograms)和其他高級統計信息:
- 直方圖:對于某些列,PostgreSQL 可以生成直方圖,以更好地了解值的分布。這對于估算復雜條件(如范圍查詢)非常有用。
- 多維統計:PostgreSQL 允許使用多維統計信息來捕獲多個列之間的相關性,幫助優化器更準確地估算選擇率。
6. 估算過程中的調整
在估算過程中,PostgreSQL 可能會根據歷史查詢的執行情況進行調整。優化器會記錄實際執行的查詢計劃的性能,以便在將來做出更好的選擇。
7. 使用 GIN 和 GiST 索引
對于使用 GIN(Generalized Inverted Index)和 GiST(Generalized Search Tree)索引的查詢,選擇率的估算可能會更復雜,因為這些索引支持多值和復雜數據類型。優化器會根據索引的特性和歷史使用情況來估算選擇率。
8. 優化器
查詢優化器(planner)使用這些選擇率來選擇最優的執行計劃。選擇率越低,通常意味著需要掃描的行數越少,從而影響執行計劃中選擇的索引和連接順序。
總結
PostgreSQL 的選擇率估算邏輯是查詢優化的重要組成部分,涉及統計信息的收集、選擇率的計算、直方圖的使用以及歷史執行情況的調整。通過這些機制,PostgreSQL 能夠更有效地選擇最佳的查詢執行計劃,從而提高查詢性能。