跳躍範圍掃描是MySQL在8.0.13版本新增長的用於提升性能的新特性,跳躍範圍掃描可使之前部分沒法使用到聯合索引的SQL利用聯合索引進行查詢,而且能夠更高效的利用聯合索引,這對於使用MySQL聯合索引進行查詢的應用意義重大。mysql
經過一個示例來解釋跳躍範圍掃描:sql
CREATE TABLE t1 (f1 INT NOT NULL, f2 INT NOT NULL, PRIMARY KEY(f1, f2));
INSERT INTO t1 VALUES(1,1), (1,2), (1,3), (1,4), (1,5),(2,1), (2,2), (2,3), (2,4), (2,5);
INSERT INTO t1 SELECT f1, f2 + 5 FROM t1;
INSERT INTO t1 SELECT f1, f2 + 10 FROM t1;
INSERT INTO t1 SELECT f1, f2 + 20 FROM t1;
INSERT INTO t1 SELECT f1, f2 + 40 FROM t1;
ANALYZE TABLE t1;
EXPLAIN SELECT f1, f2 FROM t1 WHERE f2 > 40\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
partitions: NULL
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 8
ref: NULL
rows: 53
filtered: 100.00
Extra: Using where; Using index for skip scan
1 row in set, 1 warning (0.00 sec)
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.15 |
+-----------+
1 row in set (0.00 sec)
複製代碼
在這個示例中,SELECT f1,f2 FROM t1 WHERE f2>40
在8.0.13版本以前是經過索引全掃描的方式來獲取最終的結果集,由於SELECT查詢的字段所有都是索引的組成部分。MySQL經過索引全掃描獲取全部的行記錄,而後經過f2 > 40
這個條件過濾,最終篩選出結果集返回給客戶端。bash
衆所周知,索引範圍掃描的效率確定是要高於索引全掃描的,在這個示例中,雖然查詢條件是f2 > 40
,屬於範圍查詢,可是WHERE條件中不包含f1
字段的的條件,因此沒法使用索引範圍掃描的方式過濾數據。在MySQL-8.0.13版本增長的跳躍範圍掃描特性,就是針對相似的場景的優化,跳躍範圍掃描在這個示例中實際是針對每個f1
字段的值,進行了範圍掃描,即進行了屢次範圍掃描。 針對這個示例,具體的跳躍範圍掃描過程以下:性能
f1
的第一個值:f1 = 1
f2
的條件組合:f1 = 1 AND f2 > 40
f1
的第二個值:f1 = 2
f2
的條件組合:f1 = 2 AND f2 > 40
跳躍範圍掃描實際就是將一些全掃描的場景拆分紅多個範圍掃描,利用範圍掃描的效率高於全掃描的效率,最終實現提升SQL效率。 在這個示例中,比較有跳躍範圍掃描特性的SQL執行計劃以及沒有跳躍範圍掃描特性的SQL執行計劃:優化
# 有跳躍範圍掃描特性
mysql> EXPLAIN SELECT f1, f2 FROM t1 WHERE f2 > 40\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
partitions: NULL
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 8
ref: NULL
rows: 53
filtered: 100.00
Extra: Using where; Using index for skip scan
1 row in set, 1 warning (0.00 sec)
# 沒有跳躍範圍掃描特性
mysql> EXPLAIN SELECT f1, f2 FROM t1 WHERE f2 > 40\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
partitions: NULL
type: index
possible_keys: NULL
key: PRIMARY
key_len: 8
ref: NULL
rows: 160
filtered: 33.33
Extra: Using where; Using index
1 row in set, 1 warning (0.00 sec)
複製代碼
經過執行計劃能夠看到,有跳躍範圍掃描特性的查詢掃描的行數更少且過濾性更高。ui
下面來講說跳躍範圍掃描使用一些限制以及場景:spa
([A_1,A_2...A_k],B_1,B_2...B_m,C,[,D_1,...,D_n])
,其中A部分以及D部分能夠爲空,可是B和C部分不能爲空。A_1,A_2..等表明字段值GROUP BY
或者DISTINCT
A_1,A_2...A_k
部分必須是能夠被相等的常量跳躍範圍掃描默認是開啓的,有兩種方式能夠關閉跳躍範圍掃描特性:操作系統
optimizer_switcher
變量值,默認MySQL是將optimizer_switcher
中的skip_scan
設置爲on的,能夠經過將skip_scan
設置爲off關閉跳躍範圍掃描SELECT/*+ NO_SKIP_SCAN(t1 PRIMARY) */ f1, f2 FROM t1 WHERE f2 > 40;
對於使用了跳躍範圍掃描特性的SQL,使用EXPLAIN查看其執行計劃,能夠看到:code
Using index for skip scan
跳躍範圍掃描是對使用MySQL聯合索引查詢的SQL意義重大,能在使SQL查詢效率更高,可是並非使用到跳躍範圍掃描就能表明SQL執行效率更高。在MySQL一些開發規範中,通常要求創建聯合索引時將重複值少的字段放在聯合索引前面,將重複值多的字段放在聯合索引後面,方便SQL在使用聯合索引時經過前面的字段快速過濾結果。可是在跳躍範圍掃描特性中,是遍歷前面字段的值,與後續字段的範圍查詢條件組合,進行範圍掃描查詢,那對於重複值少的字段會被拆分紅多個範圍掃描查詢,在實際使用過程當中並不必定會比索引全掃描效率更高。索引
因此我的以爲跳躍範圍掃描適用於聯合索引中前導列distinct值較少,後續字段選擇過濾性又比較好的場景,能更好的發揮跳躍範圍掃描的做用。