識別查詢處理元件

已完成

執行查詢有四個不同的階段。 依照執行順序,這些階段如下:

  1. 剖析
  2. 轉換 (重寫器)
  3. 規劃
  4. 執行

剖析器

剖析器負責檢查查詢字串是否有有效的語法。 剖析器有兩個主要部分:

  • gram.y,由一組文法規則和對應的動作所組成。
  • scan.1 為辨識識別碼與 SQL 關鍵字的「語彙分析器」。 每個關鍵字或識別碼都會觸發要建立並交接給剖析器的權杖。

剖析器會建置查詢樹狀結構,將查詢分成可識別的元件,以瞭解涉及哪些數據表、套用了哪些篩選等等。查詢樹狀結構的元件如下:

  • 命令類型 - SELECT、INSERT、UPDATE 或 DELETE。
  • Range 表格項目(RTE) - 關聯項目清單、ie 資料表、子查詢、聯結結果等等。在 SELECT 語句中,這些項目會出現在 FROM 關鍵字之後。
  • 結果關聯 - 命令 INSERT、UPDATE 和 DELETE 命令的結果關聯性,是變更生效的數據表或檢視表。
  • 目標清單 - 在 SELECT 和 FROM 關鍵詞之間識別的查詢結果。 DELETE 命令不會產生結果,因此查詢計畫器會新增特殊條目,以允許執行器尋找要刪除的資料列。 INSERT 命令會識別應該進入結果關聯的新數據列。 針對 UPDATE 命令,目標清單會描述應該取代舊資料列的新資料列。
  • 限定 - 布爾值,指定是否應該執行最終結果數據列的作業。 它對應到 SQL 語法中的 WHERE 子句。
  • 聯結樹狀 - 此樹狀可能是 FROM 項目的清單。 聯結可以依任何順序完成,或依特定順序完成,例如外部聯結。
  • 其他 - 在此階段不相關的項目,例如 ORDER BY 子句。

重寫器

剖析器的輸出會傳遞至轉換或重寫器處理序,除非找到錯誤,否則在此情況下會傳回錯誤訊息。

查詢重寫器會藉由將 規則 套用至查詢文字,來重寫查詢文字。 重寫器會將規則納入考慮,然後將修改過的查詢傳遞至查詢規劃工具。 此階段會實作資料列層級安全性。

例如,SELECT 上的規則一律會套用為最後一個步驟,包括 INSERT、UPDATE 和 DELETE 查詢。 規則也表示 UPDATE 查詢不會覆寫現有的數據列,而是插入新的數據列,並隱藏舊的數據列。 交易認可之後,VACUUM 處理序可以移除隱藏的資料列。

規劃工具

規劃者的工作是利用查詢規則,瞭解不同的執行查詢方式中哪種最快。

規劃工具會建立計劃樹狀結構,節點代表數據的實體作業。

PostgreSQL 會使用成本型查詢優化器來尋找查詢的最佳計劃。 規劃工具會評估各種執行計劃,並估計需要多少必要資源,例如 CPU 週期、I/O 作業等。此估計值接著會轉換成單位,稱為 方案成本。 選取成本最低的方案。

不過,當聯結數目增加時,可能的方案數目會以指數方式成長。 即使對於相對簡單的查詢,評估每個可能的計劃也變得不可能。 啟發學習法和演算法可用來限制可能的計劃數目。 結果是選取的方案可能不是最佳方案。 然而,這會接近最佳計畫,並在合理的時間內進行選取。

成本是規劃師的最佳估計值。 成本估計的目的是「比較」「相同」條件中「相同」查詢的不同執行計畫。 規劃工具會使用數據表和數據列上收集的統計數據來產生查詢的成本估計值。 若要讓成本估計正確,統計數據必須是最新的。

最新統計數據

查詢優化工具的規劃工具元件會使用數據表和數據列的相關統計數據來產生精確的成本估計值。

ANALYZE 會收集資料庫數據表的相關統計數據,並將結果儲存在 pg_statistic 系統目錄中。 若發生下列情況,您必須執行 ANALYZE:

  • 您已停用自動資料清理 (通常會自動分析資料表)
  • 您已停用自動資料清理,且最近尚未執行 ANALYZE
  • 上述任一項,而且有許多 INSERTS、UPDATES 或 DELETE 語句。

成本估算依賴於截至up-to的統計數據,如果統計數據過時,可能會選擇效率低下的計劃。 當沒有任何參數傳遞至 ANALYZE 時,會檢查資料庫中的每一個數據表。

ANALYZE 的語法如下:

ANALYZE [ VERBOSE ] [ ***table*** [ ( ***column*** [, ...] ) ] ]

VERBOSE 會顯示進度訊息,以顯示正在分析的數據表,以及一些統計數據。

排程 VACUUM 與 ANALYZE,以在低使用量期間每天執行。 ANALYZE 可以與其他活動平行執行,因為它只需要目標數據表的讀取鎖定。

執行者

此階段會採用規劃工具所建立的計劃,並以遞歸方式處理以擷取所需的數據列集。 每次呼叫計畫節點時,執行程式都必須傳遞一個資料列,或回報表示執行程式已完成。

執行程式會評估這四種 SQL 查詢類型:

  • SELECT
  • INSERT
  • 更新
  • 刪除

針對 SELECT,執行程式會將每個數據列傳回給用戶端作為結果集。

針對 INSERT,每個傳回的數據列都會插入指定的數據表中。 這項工作是在稱為ModifyTable的特殊最上層計劃節點中完成。

針對 UPDATE,每個計算數據列都包含所有更新的數據行值,以及目標數據列的數據列標識符。 數據會傳送至ModifyTable節點,這會建立更新的數據列,並將舊數據列標示為已刪除。

針對 DELETE,計畫傳回的唯一資料行是資料列識別碼。 ModifyTable 節點會使用資料列標識碼,將數據列標示為已刪除。