文件首頁
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


MySQL 8.4 參考手冊  /  ...  /  常數折疊最佳化

10.2.1.14 常數折疊最佳化

常數與資料行值之間的比較,若常數值相對於資料行類型超出範圍或類型錯誤,現在會在查詢最佳化期間處理一次,而不是在執行期間逐列處理。可以這種方式處理的比較為 >>=<<=<>/!==<=>

考量由下列陳述式建立的資料表

CREATE TABLE t (c TINYINT UNSIGNED NOT NULL);

查詢 SELECT * FROM t WHERE c < 256 中的 WHERE 條件包含整數常數 256,它超出 TINYINT UNSIGNED 資料行的範圍。先前,這是透過將兩個運算元都視為較大的類型來處理,但現在,由於 c 的任何允許值都小於常數,因此 WHERE 運算式可以改為折疊為 WHERE 1,因此查詢會重寫為 SELECT * FROM t WHERE 1

這使得最佳化器可以完全移除 WHERE 運算式。如果資料行 c 可以為 null(也就是說,僅定義為 TINYINT UNSIGNED),查詢會如下重寫

SELECT * FROM t WHERE ti IS NOT NULL

針對與支援的 MySQL 資料行類型比較的常數執行折疊,如下所示

  • 整數資料行類型。 整數類型會與下列類型的常數進行比較,如此處所述

    • 整數值。 如果常數超出資料行類型的範圍,則比較會折疊為 1IS NOT NULL,如已顯示。

      如果常數是範圍界限,則比較會折疊為 =。例如(使用與已定義的相同資料表)

      mysql> EXPLAIN SELECT * FROM t WHERE c >= 255;
      *************************** 1. row ***************************
                 id: 1
        select_type: SIMPLE
              table: t
         partitions: NULL
               type: ALL
      possible_keys: NULL
                key: NULL
            key_len: NULL
                ref: NULL
               rows: 5
           filtered: 20.00
              Extra: Using where
      1 row in set, 1 warning (0.00 sec)
      
      mysql> SHOW WARNINGS;
      *************************** 1. row ***************************
        Level: Note
         Code: 1003
      Message: /* select#1 */ select `test`.`t`.`ti` AS `ti` from `test`.`t` where (`test`.`t`.`ti` = 255)
      1 row in set (0.00 sec)
    • 浮點數或定點數值。如果常數是十進位類型之一(例如 DECIMALREALDOUBLEFLOAT)且具有非零的小數部分,則它們不能相等;請據此折疊。對於其他比較,請根據符號向上或向下捨入為整數值,然後執行範圍檢查,並按照先前針對整數與整數比較所述的方式處理。

      REAL 值太小而無法表示為 DECIMAL,則根據符號捨入為 .01 或 -.01,然後將其視為 DECIMAL 處理。

    • 字串類型。嘗試將字串值解釋為整數類型,然後將比較視為整數值之間的比較來處理。如果失敗,則嘗試將該值視為 REAL 來處理。

  • DECIMAL 或 REAL 資料行。十進位類型與以下類型的常數進行比較時,如這裡所述。

    • 整數值。針對資料行的整數部分執行範圍檢查。如果沒有折疊結果,則將常數轉換為與資料行值的小數位數相同的 DECIMAL,然後將其作為 DECIMAL 檢查(請參閱下文)。

    • DECIMAL 或 REAL 值。檢查溢位(即常數的整數部分位數是否多於資料行十進位類型所允許的位數)。如果溢位,則折疊。

      如果常數的小數位數多於資料行的類型,則截斷常數。如果比較運算子是 =<>,則折疊。如果運算子是 >=<=,則由於截斷而調整運算子。例如,如果資料行的類型是 DECIMAL(3,1),則 SELECT * FROM t WHERE f >= 10.13 會變成 SELECT * FROM t WHERE f > 10.1

      如果常數的小數位數少於資料行的類型,則將其轉換為具有相同位數的常數。對於 REAL 值的下溢(即,小數位數太少而無法表示),則將常數轉換為十進位 0。

    • 字串值。如果可以將該值解釋為整數類型,則將其視為整數類型處理。否則,請嘗試將其視為 REAL 處理。

  • FLOAT 或 DOUBLE 資料行。與常數比較的 FLOAT(m,n)DOUBLE(m,n) 值按如下方式處理

    如果該值溢出資料行的範圍,則折疊。

    如果該值的小數位數超過 n,則截斷,在折疊期間進行補償。對於 =<> 比較,如先前所述,折疊為 TRUEFALSEIS [NOT] NULL;對於其他運算子,則調整運算子。

    如果該值的整數位數超過 m,則折疊。

限制。在下列情況下,無法使用此最佳化

  1. 使用 BETWEENIN 進行比較時。

  2. 使用 BIT 資料行或使用日期或時間類型的資料行時。

  3. 在準備陳述的準備階段期間,儘管可以在實際執行準備陳述的最佳化階段應用。這是由於在陳述準備期間,常數的值尚未知。