常數與資料行值之間的比較,若常數值相對於資料行類型超出範圍或類型錯誤,現在會在查詢最佳化期間處理一次,而不是在執行期間逐列處理。可以這種方式處理的比較為 >
、>=
、<
、<=
、<>
/!=
、=
和 <=>
。
考量由下列陳述式建立的資料表
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 資料行類型比較的常數執行折疊,如下所示
整數資料行類型。 整數類型會與下列類型的常數進行比較,如此處所述
整數值。 如果常數超出資料行類型的範圍,則比較會折疊為
1
或IS 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)
浮點數或定點數值。如果常數是十進位類型之一(例如
DECIMAL
、REAL
、DOUBLE
或FLOAT
)且具有非零的小數部分,則它們不能相等;請據此折疊。對於其他比較,請根據符號向上或向下捨入為整數值,然後執行範圍檢查,並按照先前針對整數與整數比較所述的方式處理。若
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
,則截斷,在折疊期間進行補償。對於=
和<>
比較,如先前所述,折疊為TRUE
、FALSE
或IS [NOT] NULL
;對於其他運算子,則調整運算子。如果該值的整數位數超過
m
,則折疊。
限制。在下列情況下,無法使用此最佳化
使用
BETWEEN
或IN
進行比較時。使用
BIT
資料行或使用日期或時間類型的資料行時。在準備陳述的準備階段期間,儘管可以在實際執行準備陳述的最佳化階段應用。這是由於在陳述準備期間,常數的值尚未知。