文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 40.0Mb
PDF (A4) - 40.1Mb
手冊頁 (TGZ) - 258.2Kb
手冊頁 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


10.2.2.2 使用實體化優化子查詢

最佳化器使用實體化來啟用更有效率的子查詢處理。實體化透過將子查詢結果產生為暫存資料表(通常在記憶體中)來加速查詢執行。當 MySQL 第一次需要子查詢結果時,它會將該結果實體化為暫存資料表。之後任何時間需要結果時,MySQL 會再次參照暫存資料表。最佳化器可以使用雜湊索引為資料表建立索引,以使查找快速且成本低廉。索引包含唯一值,以消除重複項並縮小資料表。

子查詢實體化會盡可能使用記憶體中的暫存資料表,如果資料表變得太大,則會回復為磁碟上的儲存空間。請參閱第 10.4.4 節,「MySQL 中內部暫存資料表的使用」

如果未使用實體化,最佳化器有時會將非關聯子查詢重寫為關聯子查詢。例如,以下 IN 子查詢是非關聯的 (where_condition 僅涉及來自 t2 的資料行,而不涉及 t1)

SELECT * FROM t1
WHERE t1.a IN (SELECT t2.b FROM t2 WHERE where_condition);

最佳化器可能會將其重寫為 EXISTS 關聯子查詢

SELECT * FROM t1
WHERE EXISTS (SELECT t2.b FROM t2 WHERE where_condition AND t1.a=t2.b);

使用暫存資料表的子查詢實體化避免了此類重寫,並使子查詢能夠僅執行一次,而不是針對外部查詢的每一列執行一次。

為了在 MySQL 中使用子查詢實體化,必須啟用optimizer_switch 系統變數的 materialization 旗標。(請參閱第 10.9.2 節,「可切換的最佳化」。) 啟用materialization 旗標後,實體化適用於出現在任何位置(在選取清單、WHEREONGROUP BYHAVINGORDER BY 中)的子查詢述詞,對於屬於以下任何用例的述詞

  • 當沒有外部運算式 oe_i 或內部運算式 ie_i 可為 Null 時,述詞具有此形式。N 為 1 或更大。

    (oe_1, oe_2, ..., oe_N) [NOT] IN (SELECT ie_1, i_2, ..., ie_N ...)
  • 當存在單一外部運算式 oe 和內部運算式 ie 時,述詞具有此形式。運算式可以為 Null。

    oe [NOT] IN (SELECT ie ...)
  • 述詞為 INNOT IN,且 UNKNOWN (NULL) 的結果與 FALSE 的結果具有相同意義。

以下範例說明 UNKNOWNFALSE 述詞評估的等效性需求如何影響是否可以使用子查詢物化。假設 where_condition 僅涉及來自 t2 的資料行,而不涉及 t1 的資料行,因此子查詢是非相關的。

此查詢適用於物化

SELECT * FROM t1
WHERE t1.a IN (SELECT t2.b FROM t2 WHERE where_condition);

在這裡,IN 述詞傳回 UNKNOWNFALSE 並不重要。無論如何,來自 t1 的列都不會包含在查詢結果中。

不使用子查詢物化的範例是以下查詢,其中 t2.b 是一個可為 Null 的資料行

SELECT * FROM t1
WHERE (t1.a,t1.b) NOT IN (SELECT t2.a,t2.b FROM t2
                          WHERE where_condition);

以下限制適用於子查詢物化的使用

  • 內部和外部運算式的類型必須相符。例如,如果兩個運算式都是整數或都是十進位,最佳化工具也許可以使用物化,但如果一個運算式是整數,另一個是十進位,則不能使用物化。

  • 內部運算式不能是 BLOB

使用 EXPLAIN 查詢可以提供一些關於最佳化工具是否使用子查詢物化的指示

  • 與不使用物化的查詢執行相比,select_type 可能會從 DEPENDENT SUBQUERY 變更為 SUBQUERY。這表示,對於每個外部列都會執行一次的子查詢,物化使子查詢能夠僅執行一次。

  • 對於擴充的 EXPLAIN 輸出,後面 SHOW WARNINGS 顯示的文字包括 materializematerialized-subquery

如果陳述式未使用 ORDER BYLIMIT,並且最佳化工具提示或 optimizer_switch 設定允許子查詢物化,則 MySQL 也可以將子查詢物化套用至使用 [NOT] IN[NOT] EXISTS 子查詢述詞的單一資料表 UPDATEDELETE 陳述式。