B-Tree 索引类型详解
索引有很多种类型,可以为不同的应用场景提供更好的性能。在 MySQL 中,索引是在存储引擎层实现的。接下来重点介绍四种常见的索引类型:B-Tree 索引、哈希索引、空间数据索引(R-Tree)、全文索引。这部分内容分为上下两个小节,本小节重点介绍 B-Tree 索引。
1. B-Tree 索引
B-Tree 索引是最常见的索引之一,当大家在谈论索引的时候,如果没有特别说明,那多半说的就是 B-Tree 索引。在 MySQL 中,大多数的存储引擎都支持 B-Tree 索引。
1.1 存储结构
B-Tree 对索引列的值是按顺序存储的,并且每一个叶子页到根的距离相同。B-Tree 索引可以加快数据查找的速度,因为存储引擎不需要全表扫描来获取数据,只要从索引的根节点开始搜索即可。
以表 customer 为例,我们来看看索引是如何组织数据的存储的。
mysql> create table customer( id int, last_name varchar(30), first_name varchar(30), birth_date date, gender char(1), key idx1_customer(last_name,first_name,birth_date) );
如图,对于表中的每行数据,索引包含了 last_name、first_name 和 birth_date 的值。
1.2 适合 B-Tree 索引的查询类型
全值匹配
和索引中的所有列进行匹配,如查找姓名为 George Bush、1960-08-08 出生的客户。
mysql> explain select * from customer where first_name='George' and last_name='Bush' and birth_date='1960-08-08'\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: customer partitions: NULL type: refpossible_keys: idx1_customer key: idx1_customer key_len: 190 ref: const,const,const rows: 1 filtered: 100.00 Extra: NULL1 row in set, 1 warning (0.00 sec)
匹配最左前缀
只使用索引的第一列,如查找所有姓氏为 Bush 的客户:
mysql> explain select * from customer where last_name='Bush'\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: customer partitions: NULL type: refpossible_keys: idx1_customer key: idx1_customer key_len: 93 ref: const rows: 1 filtered: 100.00 Extra: NULL1 row in set, 1 warning (0.00 sec)
匹配列前缀
只匹配某一列的值的开头部分,如查找所有以 B 开头的姓氏的客户,这里使用了索引的第一列:
mysql> explain select * from customer where last_name like 'B%'\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: customer partitions: NULL type: rangepossible_keys: idx1_customer key: idx1_customer key_len: 93 ref: NULL rows: 1 filtered: 100.00 Extra: Using index condition1 row in set, 1 warning (0.00 sec)
匹配范围值
查找所有姓氏在 Allen 和 Bush 之间的客户,这里使用了索引的第一列:
mysql> explain select * from customer where last_name between 'Allen' and 'Bush'\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: customer partitions: NULL type: rangepossible_keys: idx1_customer key: idx1_customer key_len: 93 ref: NULL rows: 1 filtered: 100.00 Extra: Using index condition1 row in set, 1 warning (0.00 sec)
精确匹配某一列,并范围匹配另一列
第一列全匹配,第二列范围匹配,如查找姓氏为 Bush,名字以 G 开头的客户:
mysql> explain select * from customer where last_name='Bush' and first_name like 'G'\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: customer partitions: NULL type: rangepossible_keys: idx1_customer key: idx1_customer key_len: 186 ref: NULL rows: 1 filtered: 100.00 Extra: Using index condition1 row in set, 1 warning (0.00 sec)
只访问索引的查询
只需要访问索引即可获取数据,不需要回表访问数据行,这种查询也叫覆盖索引:
mysql> explain select last_name from customer where last_name='Bush'\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: customer partitions: NULL type: refpossible_keys: idx1_customer key: idx1_customer key_len: 93 ref: const rows: 1 filtered: 100.00 Extra: Using index1 row in set, 1 warning (0.00 sec)
除了上述这些查询类型外,索引还可以用于 order by 排序操作,因为索引中的节点是有序的。如果 B-Tree 可以按照某种方式查找到数据,那么也可以按照这种方式进行排序。
1.3 B-Tree 索引的限制
如果不是按照索引的最左列开始查找数据,则无法使用索引。如查找名字为 George 的客户:
mysql> explain select * from customer where first_name='George'\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: customer partitions: NULL type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1 filtered: 100.00 Extra: Using where1 row in set, 1 warning (0.00 sec)
不能跳过索引的列。如查找姓氏为 Bush,生日为 1960-08-08 的客户,这种查询只能使用索引的第一列:
mysql> explain select * from customer where last_name='Bush' and birth_date='1960-08-08'\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: customer partitions: NULL type: refpossible_keys: idx1_customer key: idx1_customer key_len: 93 ref: const rows: 1 filtered: 100.00 Extra: Using index condition1 row in set, 1 warning (0.00 sec)
如果查询中有某个列的范围查询,在其右边的列都无法使用索引进行查找数据。如查找姓氏为以 B 开头,名字为 George 的客户。这个查询只能使用第一列,因为 like 是一个范围查询:
mysql> explain select * from customer where last_name like 'B%' and first_name='George'\G;*************************** 1. row *************************** id: 1 select_type: SIMPLE table: customer partitions: NULL type: rangepossible_keys: idx1_customer key: idx1_customer key_len: 186 ref: NULL rows: 1 filtered: 100.00 Extra: Using index condition1 row in set, 1 warning (0.00 sec)
2. 小结
本小节介绍了 B-Tree 索引的存储结构、适合 B-Tree 索引的查询类型和相关限制,从中我们可以看出,索引列的顺序非常重要。在某些应用场景,可能需要创建相同列,但顺序不同的索引,来满足性能的优化。
更新于:3个月前相关文章
- 【说站】php常见运行模式详解
- 【说站】javascript字符串类型的转换
- 【说站】python列表索引的两种用法
- 【说站】python字符串索引的用法
- 【说站】java泛型中类型擦除的转换
- 【说站】MySQL的五种索引类型极其特点
- 【说站】java反射机制原理详解
- 【说站】java内存屏障有哪些类型
- 【说站】php数组排序并保持索引关系
- 【说站】php数组排序保持索引
- 【说站】python切片如何进行索引
- 【说站】Java如何创建类型实例
- iOS开发xconfig和script脚本使用详解
- java 安全沙箱模型详解
- git clean 命令详解
- HTTP状态码详解对照表
- git switch 命令详解
- git rebase 命令详解
- JS 数组详解【编程笔记】
- 简单描述 MySQL 中,索引,主键,唯一索引,联合索引 的区别,对数据库的性能有什么影响(从读写两方面)