此最佳化可提高非索引欄與常數之間直接比較的效率。在這種情況下,條件會被「下推」至儲存引擎進行評估。此最佳化只能由 NDB
儲存引擎使用。
對於 NDB Cluster,此最佳化可以消除在叢集的資料節點與發出查詢的 MySQL 伺服器之間透過網路傳送不相符列的需求,並且可以將使用條件下推的查詢速度提高 5 到 10 倍,而未使用條件下推的情況下則無法。
假設 NDB Cluster 資料表的定義如下
CREATE TABLE t1 (
a INT,
b INT,
KEY(a)
) ENGINE=NDB;
引擎條件下推可以用於包含非索引欄與常數之間比較的查詢,例如此處顯示的查詢
SELECT a, b FROM t1 WHERE b = 10;
可以使用 EXPLAIN
的輸出查看引擎條件下推的使用情況
mysql> EXPLAIN SELECT a, b FROM t1 WHERE b = 10\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 10
Extra: Using where with pushed condition
但是,引擎條件下推無法與下列查詢一起使用
SELECT a,b FROM t1 WHERE a = 10;
此處不適用引擎條件下推,因為欄位 a
上存在索引。(索引存取方法會更有效率,因此會優先選用,而不是條件下推。)
當使用 >
或 <
運算子將索引欄與常數進行比較時,也可以使用引擎條件下推
mysql> EXPLAIN SELECT a, b FROM t1 WHERE a < 2\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: range
possible_keys: a
key: a
key_len: 5
ref: NULL
rows: 2
Extra: Using where with pushed condition
引擎條件下推的其他支援比較包括下列項目
欄位
[NOT] LIKE模式
模式
必須是包含要比對模式的字串文字;如需語法,請參閱 第 14.8.1 節,「字串比較函式與運算子」。欄位
IS [NOT] NULL欄位
IN (值清單
)值清單
中的每個項目都必須是常數、文字值。欄位
BETWEEN常數1
AND常數2
常數1
和常數2
都必須是常數、文字值。
在先前清單中的所有情況下,都有可能將條件轉換為欄位與常數之間一個或多個直接比較的形式。
引擎條件下推預設為啟用。若要在伺服器啟動時停用它,請將 optimizer_switch
系統變數的 engine_condition_pushdown
旗標設定為 off
。例如,在 my.cnf
檔案中,使用以下這些行
[mysqld]
optimizer_switch=engine_condition_pushdown=off
在執行階段,可以像這樣停用條件下推:
SET optimizer_switch='engine_condition_pushdown=off';
限制。引擎條件下推受限於以下限制:
先前,引擎條件下推僅限於參考條件要下推的同一個表格的欄位值的術語。在 NDB 9.0 中,也可以從查詢計畫中較早的表格參考下推條件中的欄位值。這減少了在聯結處理期間 SQL 節點必須處理的列數。篩選也可以在 LDM 執行緒中平行執行,而不是在單個 mysqld 程序中執行。這有可能顯著提高查詢效能。
如果同一個聯結巢狀結構中使用的任何表格,或其所依賴的任何較高聯結巢狀結構中的任何表格上,沒有無法下推的條件,則 NDB
可以使用掃描來下推外部聯結。如果採用的最佳化策略是 firstMatch
,則半聯結也是如此(請參閱 使用半聯結轉換最佳化 IN 和 EXISTS 子查詢謂詞)。
在以下兩種情況下,聯結演算法不能與參考先前表格中的欄位結合使用:
當任何被參考的先前表格位於聯結緩衝區中時。在這種情況下,從掃描篩選的表格中檢索的每一列都會與緩衝區中的每一列進行比對。這表示在產生掃描篩選器時,沒有可從中擷取欄位值的單一特定列。
當欄位來自已下推聯結中的子運算時。這是因為在產生掃描篩選器時,尚未擷取聯結中來自上層運算的參考列。
只要滿足先前列出的要求,就可以下推聯結中來自上層表格的欄位。以下顯示使用先前建立的表格 t1
的此類查詢範例:
mysql> EXPLAIN
-> SELECT * FROM t1 AS x
-> LEFT JOIN t1 AS y
-> ON x.a=0 AND y.b>=3\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: x
partitions: p0,p1
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
filtered: 100.00
Extra: NULL
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: y
partitions: p0,p1
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
filtered: 100.00
Extra: Using where; Using pushed condition (`test`.`y`.`b` >= 3); Using join buffer (hash join)
2 rows in set, 2 warnings (0.00 sec)