索引跳跃扫描

索引跳跃扫描(Index Skip Scanning)是一种数据库查询优化技术,主要用于索引查找过程中。它利用了索引的特性,在索引中寻找符合查询条件的记录的一种高效方法。
### 基本原理
在数据库中,索引是为了加快数据检索速度而创建的数据结构。索引跳跃扫描的基本思想是:
1. "定位起始点":根据查询条件,首先在索引中找到第一个可能满足条件的记录。 2. "跳过不满足条件的记录":在索引中找到满足条件的起始点后,通过索引的顺序性,直接跳过那些不满足查询条件的记录。 3. "重复过程":重复上述步骤,直到找到所有满足条件的记录。
### 优点
- "提高效率":通过跳过不满足条件的记录,索引跳跃扫描可以显著减少需要访问的索引记录数,从而提高查询效率。 - "减少I/O操作":由于减少了访问索引记录的数量,索引跳跃扫描可以减少磁盘I/O操作,提高系统性能。
### 缺点
- "适用性":索引跳跃扫描主要适用于索引顺序性较好的情况,对于随机分布的索引可能效果不佳。 - "复杂度":实现索引跳跃扫描需要一定的算法设计,对于复杂的查询条件可能需要更复杂的算法。
### 应用场景
- 当查询条件涉及多个字段,且索引覆盖了这些字段时。 - 当查询条件中的字段顺序与索引的顺序相同时

相关内容:

lass="xiangguan" id="content">

在前面的复合索引文章里讲到过,复合索引要满足最左前缀匹配原则,即不能跳过索引的前导列而单独使用索引的后面的列。

如果有查询复合索引(a,b),查询为select * from t where b=xx,此查询是否一定不能走索引呢?

表结构如下:

mysql> desc emps;
+------------+---------------+------+-----+---------+----------------+
| Field      | Type          | Null | Key | Default | Extra          |
+------------+---------------+------+-----+---------+----------------+
| id         | int           | NO   | PRI | NULL    | auto_increment |
| emp_no     | int           | NO   |     | NULL    |                |
| birth_date | date          | NO   |     | NULL    |                |
| first_name | varchar(14)   | NO   | MUL | NULL    |                |
| last_name  | varchar(16)   | NO   | MUL | NULL    |                |
| gender     | enum('m','f') | NO   |     | NULL    |                |
| hire_date  | date          | NO   |     | NULL    |                |
+------------+---------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)

在(gender,first_name)建组合索引

mysql> create index gf_ck on emps(gender,first_name);
Query OK, 0 rows affected (2.08 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show indexes from emps;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| emps  |          0 | PRIMARY  |            1 | id          | A         |      299150 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| emps  |          1 | gf_ck    |            1 | gender      | A         |           1 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| emps  |          1 | gf_ck    |            2 | first_name  | A         |        2476 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
3 rows in set (0.01 sec)

查看select gender,first_name from emps where first_name='Anneke';的执行计划

mysql> desc select gender,first_name from emps where first_name='Anneke';
+----+-------------+-------+------------+-------+---------------+-------+---------+------+-------+----------+----------------------------------------+
| id | select_type | table | partitions | type  | possible_keys | key   | key_len | ref  | rows  | filtered | Extra                                  |
+----+-------------+-------+------------+-------+---------------+-------+---------+------+-------+----------+----------------------------------------+
|  1 | SIMPLE      | emps  | NULL       | range | gf_ck         | gf_ck | 59      | NULL | 29915 |   100.00 | Using where; Using index for skip scan |
+----+-------------+-------+------------+-------+---------------+-------+---------+------+-------+----------+----------------------------------------+
1 row in set, 1 warning (0.00 sec)

看到查询走了复合索引。这个查询违反了上面所说的最左前缀原则确走了索引,是不是最左前缀原则是错的呢?答案是否定的。

MySQL中有一种叫做索引跳跃扫描的优化,当查询条件中跳过了前导列,使用了后面的列时,如果跳过的前导列的唯一值不多时,查询是可以走复合索引的。如上面的示例。

索引跳跃扫描原理:

1.将查询按照前导列拆分成多个select组,让后将每个组的where条件中加上跳过的前导列=值条件,上面的示例会拆成如下

select gender,first_name from emps where gender='F' and first_name='Anneke';
union all
select gender,first_name from emps where gender='M'  first_name='Anneke';

2.使用union all将所有拆分的select组的结果集联合起来,最后将整个联合的结果集作为最终的结果集返回给客户端。

总结:

索引跳跃扫描并没有违反复合索引的最左前缀原则,只是优化器使用了一种巧妙的方式让用户误以为跳过了前导列。能使用索引跳跃扫描的前提是跳过的前导列唯一值不多。如上面的示例查询gender列只有'F'和'M'两个值。

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章