Skip Scan- MySQL8.0新增的范围访问优化方法

2020-05-26  本文已影响0人  月饮沙

本文问题

  1. MySQL8.0的哪个版本对范围扫描进行了额外的优化?
  2. Skip Scan的过程是怎样的?
  3. 在什么情况下,可以使用Skip Scan
  4. 如何查看一个查询是否使用了Skip Scan
  5. 如何禁用Skip Scan

Skip Scan 范围访问方法

假设有以下情形:

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;

要执行这个查询, MySQL可以选择索引扫描来获取符合条件的行(索引中包括所有查询的列),然后应用WHERE中的条件f2 > 40来生成最终的结果集。

Skip Scan过程

范围扫描比索引扫描更有效率,但是由于在索引的第一列f1上没有条件,无法使用范围扫描。但是,从MySQL8.0.13开始,优化器可以执行多范围扫描,对于f1中的每个值,使用一种叫做Skip Scan的方式。这类似于GROUP BYLoose Index Scan优化。

过程:

  1. 跳过索引的第一部分f1(索引前缀)
  2. 对于每个不同的索引前缀值,对索引的剩余部分,根据f2 > 40这个条件执行一个子范围扫描。

对于上述的情景,这个算法的过程如下:

  1. 获取索引第一部分的第一个值(f1 = 1
  2. 基于索引的第一和第二部分构建范围(f1 = 1 AND f2 > 40
  3. 执行范围扫描
  4. 过去索引第一部分的下一个不同值(f1 = 2
  5. 基于索引的第一和第二部分构建范围(f1 = 2 AND f2 > 40
  6. 执行范围扫描

Skip Scan条件

使用这种策略可以减少访问的行数量,因为对于每个构建的范围,MySQL跳过了那些不符合条件的行。Skip Scan访问方法适用于以下条件:

Skip Scan的EXPLAIN输出

使用Skip ScanEXPLAIN中的输出如下:

在优化器跟踪的输出为skip scan元组:

"skip_scan_range": {
  "type": "skip_scan",
  "index": index_used_for_skip_scan,
  "key_parts_used_for_access": [key_parts_used_for_access],
  "range": [range]
}

在优化器跟踪的输出中,还可能会存在"best_skip_scan_summary"元组。如果Skip Scan被选作是范围访问的最佳变体,记录"chosen_range_access_summary"。如果Skip Scan被选作为总体最好的访问方法,还会存在best_access_path元组。

禁用Skip Scan

可以使用optimizer_switch变量中的skip_scan标志来决定是否启用Skip Scan,默认启用,可以设置skip_scan=off来进行禁用

问题答案

  1. MySQL8.0的哪个版本对范围扫描进行了额外的优化?
    MySQL8.0.13开始 可以使用Skip Scan方法进行范围扫描
    当要查询的列都在索引中时,即使WHERE中的条件不是索引的第一部分,也可以使用索引。
  2. Skip Scan的过程是怎样的?
    将索引的第一部分拆分为多个等值表达式,和索引的第二部分合并构成范围条件,然后进行范围扫描查询
    例如:
index on (c1,c2)
select c1,c2 from t1 where c2>100;
过程:
select c1,c2 from t1 where c1=value1 and c2>100;
select c1,c2 from t1 where c1=value2 and c2>100;
……
  1. 在什么情况下,可以使用Skip Scan
  1. 如何查看一个查询是否使用了Skip Scan
    EXPLAIN中的Extra列中显示Using index for skip scan表示使用了Skip Scan
    可以在优化器跟踪中查看到输出:
"skip_scan_range": {
  "type": "skip_scan",
  "index": index_used_for_skip_scan,
  "key_parts_used_for_access": [key_parts_used_for_access],
  "range": [range]
}
  1. 如何禁用Skip Scan
    设置optimizer_switchskip_scan标志为off可以禁用Skip Scan
上一篇下一篇

猜你喜欢

热点阅读