此最佳化可提高非索引欄位與常數之間直接比較的效率。在這種情況下,條件會「下推」至儲存引擎以進行評估。此最佳化只能由 NDB
儲存引擎使用。
對於 NDB 叢集,此最佳化可以消除在叢集的資料節點和發出查詢的 MySQL 伺服器之間,透過網路傳送不符合的列的需求,並且可以將使用條件下推的查詢速度提高 5 到 10 倍,與未使用條件下推的情況相比。
假設 NDB 叢集資料表的定義如下
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
引擎條件下推的其他支援比較包括以下
column
[NOT] LIKEpattern
pattern
必須是包含要比對之模式的字串常值;有關語法,請參閱 第 14.8.1 節「字串比較函式和運算子」。column
IS [NOT] NULLcolumn
IN (value_list
)value_list
中的每個項目都必須是常數、常值。column
BETWEENconstant1
ANDconstant2
constant1
和constant2
都必須是常數、常值。
在前面清單中的所有情況下,條件都有可能轉換為欄位與常數之間的一或多個直接比較的形式。
引擎條件下推預設為啟用。若要在伺服器啟動時停用它,請將 optimizer_switch
系統變數的 engine_condition_pushdown
旗標設定為 off
。例如,在 my.cnf
檔案中,使用這些行
[mysqld]
optimizer_switch=engine_condition_pushdown=off
在執行階段,像這樣停用條件下推
SET optimizer_switch='engine_condition_pushdown=off';
限制。 引擎條件下推受到以下限制
先前,引擎條件下推僅限於參照與條件被推送到的同一資料表的欄位值。在 NDB 8.4 中,查詢計劃中較早出現的資料表的欄位值也可以從推送的條件中參照。這減少了聯結處理期間 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)