文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
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 旗標後,實體化適用於任何位置(在 select 清單、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 是一個可為空的欄位。

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

MySQL 也可以將子查詢實體化應用於使用 [NOT] IN[NOT] EXISTS 子查詢述詞的單表 UPDATEDELETE 陳述式,前提是該陳述式不使用 ORDER BYLIMIT,並且最佳化工具提示或 optimizer_switch 設定允許子查詢實體化。