文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美國信紙尺寸) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  列建構子表達式最佳化

10.2.1.22 列建構子表達式最佳化

列建構子允許同時比較多個值。例如,以下兩個語句在語意上是等效的

SELECT * FROM t1 WHERE (column1,column2) = (1,1);
SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;

此外,最佳化工具會以相同的方式處理這兩個表達式。

如果列建構子資料行未涵蓋索引的前綴,則最佳化工具不太可能使用可用的索引。考量以下具有 (c1, c2, c3) 主索引鍵的資料表

CREATE TABLE t1 (
  c1 INT, c2 INT, c3 INT, c4 CHAR(100),
  PRIMARY KEY(c1,c2,c3)
);

在此查詢中,WHERE 子句使用索引中的所有資料行。但是,列建構子本身不涵蓋索引前綴,導致最佳化工具僅使用 c1key_len=4c1 的大小)

mysql> EXPLAIN SELECT * FROM t1
       WHERE c1=1 AND (c2,c3) > (1,1)\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: const
         rows: 3
     filtered: 100.00
        Extra: Using where

在這種情況下,使用等效的非建構子表達式重寫列建構子表達式可能會導致更完整的索引使用。對於給定的查詢,列建構子和等效的非建構子表達式如下

(c2,c3) > (1,1)
c2 > 1 OR ((c2 = 1) AND (c3 > 1))

將查詢重寫為使用非建構子表達式會導致最佳化工具使用索引中的所有三個資料行(key_len=12

mysql> EXPLAIN SELECT * FROM t1
       WHERE c1 = 1 AND (c2 > 1 OR ((c2 = 1) AND (c3 > 1)))\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: range
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 12
          ref: NULL
         rows: 3
     filtered: 100.00
        Extra: Using where

因此,為了獲得更好的結果,請避免將列建構子與 AND/OR 表達式混用。請使用其中一種即可。

在某些條件下,最佳化工具可以將範圍存取方法應用於具有列建構子引數的 IN() 表達式。請參閱 列建構子表達式的範圍最佳化