MySQL索引有哪些分类,你真的清楚吗?
MySQL官⽅对索引的定义是:索引(Index)是帮助MySQL⾼效获取数据的数据结构。索引最形象的⽐喻就是图书的⽬录。注意只有在⼤量数据中查询时索引才显得有意义。
在MySQL中索引是在存储引擎层实现的,⽽不是在服务器层实现的,所以不同存储引擎具有不同的索引类型和实现。常见的索引分类如下:
按数据结构分类:B+tree索引、Hash索引、Full-text索引。
按物理存储分类:聚集索引、⾮聚集索引(也叫⼆级索引、辅助索引)。
按字段特性分类:主键索引(PRIMARY KEY)、唯⼀索引(UNIQUE)、普通索引(INDEX)、全⽂索引(FULLTEXT)。
按字段个数分类:单列索引、联合索引(也叫复合索引、组合索引)。
按数据结构分类
mysql语句分类MySQL索引按数据结构分类可分为:B+tree索引、Hash索引、Full-text索引。
InnoDB MyISAM Memory B+tree索引√√√
Hash索引×××
Full-text索引√(MySQL5.6.4)√×
注:InnoDB实际上也⽀持Hash索引,但是InnoDB中Hash索引属于是⾃适应Hash索引,它的创建过程由存储引擎引擎⾃动优化创建,不能⼈为⼲预是否为表创建Hash索引
B+tree 索引是MySQL中被存储引擎采⽤最多的索引类型。它适⽤于全键值、键值范围和最左前缀查。使⽤联合索引时,如果不是按照索引列的顺序进⾏查,则⽆法使⽤索引。除了适⽤于查,还可以⽤于排序和分组。
1. B+tree索引
在MySQL中为什么会选⽤B+tree做索引结构呢?
B+tree 是在B tree基础上的⼀种优化,其更适合做存储索引结构。在 B+tree 中,⾮叶⼦节点上仅存储键值,不存储数据;⽽所有数据记录均存储在叶⼦节点上,并且数据是按照顺序排列的。此外在 B+tree 中各个数据页之间是通过双向链表连接的,叶⼦节点中的数据是通过单向链表连接的。B+tree 的结构图如下:
B+tree 结构实现数据索引具有如下优点:
a. ⾮叶⼦节点上可以存储更多的键值,相应的树的阶数(节点的⼦节点树)就会更⼤,树也就会变得更矮更胖。这样⼀来我们查数
据进⾏磁盘I/O的次数就会⼤⼤减少,数据查询的效率也会更快。
网页设计按钮怎么设成超链接b. 所有数据记录都有序存储在叶⼦节点上,就会使得范围查,排序查,分组查以及去重查变得异常简单。
c. 数据页之间、数据记录之间都是通过链表链接的,有了这个结构的⽀持就可以⽅便的在数据查询后进⾏升序或者降序操作。
c. 数据页之间、数据记录之间都是通过链表链接的,有了这个结构的⽀持就可以⽅便的在数据查询后进⾏升序或者降序操作。
2. Hash索引
Memory引擎默认⽀持哈希索引,如果多个Hash值相同,出现哈希碰撞,那么索引就以链表⽅式存储。(这有点类似于Java中的HashMap,哈哈~)InnoDB或MyISAM存储引擎页⽀持Hash索引,但是需要通过伪Hash索引来实现,叫⾃适应Hash索引。
Hash索引是基于Hash算法实现的,如上图所⽰,我们将⼀系列的最终的键值通过哈希函数转化为存储实际数据桶的地址数值。值本⾝存储的地址就是基于哈希函数的计算结果,⽽搜索的过程就是利⽤哈安卓开发简单的app
希函数从元数据中推导出桶的地址。(对Hash算法不太理解就往这⾥看:) 所以基于Hash索引结构的特殊性,其检索效率⾮常⾼,索引的检索可以⼀次定位,不像B-Tree索引需要从根节点到枝节点,最后才能访问到页节点这样多次的I/O访问,所以Hash索引在精确查询时的效率要远⾼于B-Tree索引。虽然Hash索引效率⾼,但是Hash索引本⾝由于其特殊性也带来了很多限制和弊端,主要有以下这些:
a. Hash索引仅仅能满⾜等值查询,不能进⾏范围查询
由于Hash索引⽐较的是进⾏Hash运算之后的Hash值,所以它只能⽤于等值的过滤,不能⽤于基于范围的过滤,因为经过相应的Hash算法处理之后的Hash值的⼤⼩关系,并不能保证和Hash运算前完全⼀样。
b. Hash索引⽆法通过操作索引来排序
由于 Hash索引中存放的是经过 Hash 计算之后的Hash值,⽽且Hash值的⼤⼩关系并不⼀定和Hash运算前的键值完全⼀样,所以数据库⽆法利⽤索引的数据来避免任何排序运算。
c. 组合Hash索引不能利⽤部分索引键进⾏查询
对于组合Hash索引,索引在计算 Hash 值的时候是组合索引键合并后再⼀起计算 Hash 值,⽽不是单
独计算 Hash值,所以通过组合索引的前⾯⼀个或⼏个索引键进⾏查询的时候,Hash 索引也⽆法被利⽤。
d. Hash索引依然需要回表扫描
Hash索引是将索引键通过 Hash 运算之后,将Hash运算结果的Hash值和所对应的⾏指针信息存放于⼀个 Hash 表中,由于不同索引键可能存在相同 Hash 值,所以即使取满⾜某个 Hash 键值的数据的记录条数,也⽆法从Hash索引中直接完成查询,还是要通过访问表中的实际数据进⾏相应的⽐较,并得到相应的结果。
e. Hash索引遇到⼤量Hash值相等的情况后性能并不⼀定就会⽐B-Tree索引⾼
区分度低的索引键(如,性别),如果创建Hash索引,那么将会存在⼤量记录指针信息存于同⼀个Hash值相关联。这样要定位某⼀条记录时就会⾮常⿇烦,会浪费多次表数据的访问,⽽造成整体性能低下。
3. Full-text索引数据库的transaction
Full-text索引⼀般使⽤倒排索引实现。倒排索引同B+树索引⼀样,也是⼀种索引结构。
MySQL中InnoDB存储引擎在之前版本中是不⽀持全⽂检索的,要使⽤全⽂检索的话只能使⽤MySIAM存储引擎。在 MySQL 5.6.4
版本中InnoDB存储引擎才开始⽀持Full-text索引。
对于⽂本类型的⼤对象,或者较⼤的CHAR类型的数据,如果使⽤普通索引,那么匹配⽂本前⼏个字符还是可⾏的,但是想要匹配⽂本中间的⼏个单词,那么就要使⽤LIKE %word%来匹配,这样需要很长的时间来处理,响应时间会⼤⼤增加,这种情况,就可使⽤时FULLTEXT索引了,在⽣成FULLTEXT索引时,会为⽂本⽣成⼀份单词的清单,在索引时及根据这个单词的清单来索引。
Full-text索引的查询有⾃⼰特殊的语法,⽽不能使⽤ LIKE 模糊查询的语法,语法如下:
SELECT*FROM table_name MATCH(ft_index) AGAINST('查询字符串');
specific是什么意思按物理存储分类
MySQL索引按叶⼦节点存储的是否为完整表数据分为:聚集索引、⾮聚集索引(也叫⼆级索引、辅助索引)。
1. 聚簇索引
聚簇索引就是按照每张表的主键构造⼀颗 B+tree,同时叶⼦节点中存放的就是整张表的⾏记录数据,聚集索引的叶⼦节点被称为数据页。
InnoDB表要求必须有聚簇索引,默认在主键字段上建⽴聚簇索引,在没有主键字段的情况下,表的第⼀个⾮空的唯⼀索引将被建⽴为聚簇索引,在前两者都没有的情况下,InnoDB将⾃动⽣成⼀个隐式的⾃增id列,并在此列上建⽴聚簇索引。
2. ⾮聚集索引(也叫⼆级索引、辅助索引)
⾮聚集索引的结构和聚集索引基本相同(⾮叶⼦结点存储的都是索引指针),区别在于叶⼦节点存放的不是⾏数据⽽是数据主键。因此在使⽤⾮聚集索引进⾏查时,需要先查到主键值,然后再到聚集索引中进⾏查。
两种索引的区别:每个索引上包含的字段内容不同,聚集索引包含所有真实的物理数据,⾮聚集索引只包含索引字段和主键字段。此外,聚集索引⼀个表只能有⼀个,⽽⾮聚集索引⼀个表可以存在多个。
那⾮聚集索引这种查询⽅式算不算回表呢?
回表查询简单来说就是通过⾮聚集索引查询数据时,得不到完整的数据内容,需要再次查询主键索引来获得数据内容。
所以如果使⽤⾮聚集索引后还需要使⽤其他字段的(包括在where条件中或者select⼦句中),则需要通过主键索引回表到聚集索引获取其他字段。如果是⾮聚集索引可以满⾜SQL语句的所有字段的,则被称为全覆盖索引,没有回表开销。
避免回表查询问题,常见的⽅式就是建⽴联合索引(组合索引),实现索引覆盖,从⽽避免回表查询。索引覆盖就是指索引的叶⼦节点已经包含了查询的数据,满⾜查询要求,没必要再回表进⾏查询。
按字段特性分类
MySQL索引按字段特性分类可分为:主键索引(PRIMARY KEY)、唯⼀索引(UNIQUE)、普通索引(INDEX)、全⽂索引(FULLTEXT)。
1. 主键索引(PRIMARY KEY)
建⽴在主键上的索引被称为主键索引,⼀张数据表只能有⼀个主键索引,索引列值不允许有空值,通常在创建表时⼀起创建。
2. 唯⼀索引(UNIQUE)
建⽴在UNIQUE字段上的索引被称为唯⼀索引,⼀张表可以有多个唯⼀索引,索引列值允许为空,列值中出现多个空值不会发⽣重复冲突。
3. 普通索引(INDEX)
建⽴在普通字段上的索引被称为普通索引。
4. 全⽂索引(FULLTEXT)
MyISAM 存储引擎⽀持Full-text索引,⽤于查⽂本中的关键词,⽽不是直接⽐较是否相等。Full-text索引⼀般使⽤倒排索引实现,它记录着关键词到其所在⽂档的映射。
InnoDB 存储引擎在 MySQL 5.6.4 版本中也开始⽀持Full-text索引。
按索引字段个数分类
MySQL索引按字段个数分类可分为:单列索引、联合索引(也叫复合索引、组合索引)。
1. 单列索引
建⽴在单个列上的索引被称为单列索引。
extendwith2. 联合索引(复合索引、组合索引)
建⽴在多个列上的索引被称为联合索引,⼜叫复合索引、组合索引。在MySQL中使⽤联合索引时要遵循最左前缀匹配原则。所以我们需要注意如下⼏个⽅⾯:
a. 实际业务场景中创建联合索引时,我们应该把识别度⽐较⾼的字段放在前⾯,提⾼索引的命中率,充分的利⽤索引。
b. 创建联合索引后,该索引的任何最左前缀都可以⽤于查询。⽐如当你有⼀个联合索引(col1, col2, col3),该索引的所有最左前缀为
(col1)、(col1, col2)、(col1, col2, col3),包含这些列的所有查询都会使⽤该索引进⾏查询。
c. 虽然联合索引可以避免回表查询,提⾼查询速度,但同时也会降低表数据更新的速度。因为联合索引列更新时,MySQL不仅要保存
数据,还要维护⼀下索引⽂件。所以不要盲⽬使⽤,应根据业务需求来创建。
(完)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论