🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 索引的作用 >[success] * 索引大大减少服务器需要扫描的数据量 > * 帮助服务器避免排序和临时表 > * 将随机I/O变成顺序I/O > * 提高查询速度 >[warning] * 降低了写的速度,占用磁盘 > * 5.0版本前只会使用一个索引,5.1引入了索引合并`index merge` ### **使用场景** * 中到大型表,索引非常有效 * 特大型的表,建立和使用索引的代价也增长,可以使用分区技术来解决 ## **索引类型** > * `B+Tree ` `Hash` > * 查询时间。B+ Tree为`O(log(n))`,与树的高度有关;Hash为`O(1)` > * 适用范围。在内存中,红黑树比B树效率更高;若是涉及磁盘操作,则B树更优 ## **类型区别** >[success] * 索引的树型数据结构为什么使用B+树,而非B树或红黑树? > * * B树需要做局部的中序遍历,可能要跨层访问。 > * * 而**B+树由于所有数据都在叶子结点,不用跨层,同时由于有链表结构,只需要找到首尾,通过链表就能把所有数据取出。** > * 为什么常用B+ Tree而非Hash作为索引类型? > * * 数据库中的索引一般是在磁盘上,数据量大的情况可能无法一次装入内存,B+树的设计可以允许数据分批加载,同时树的高度较低,提高查找效率。 > * * 注:哈希索引数据并不是按照索引列的值顺序存储的,故无法用于排序 > * * 哈希索引只支持等值比较查询,如:=、in()、<=>(安全比较运算符,用来做 NULL 值的关系运算),不支持任何范围查询 **** ## **索引分类** > * 普通索引:最基本的索引,没有任何约束限制 > * 唯一索引:与普通索引类似,但是具有唯一性约束 > * 主键索引:特殊的唯一索引,不允许有空置 > * 一个表只能有一个主键索引,可以有多个唯一索引 > * 主键可以与外键构成参照完整性约束,防止数据不一致 > * 组合索引:将多个列组合在一起创建索引,可以覆盖多个列 > * 外键索引:只有InnoDB类型的表才可以使用,保证数据的一致性、完整性和实现级联操作 > * 全文索引:MySql自带的全文索引只能用于MyISAM,并且只能对英文进行全文检索,全文索引(`FULL TEXT`)。目前只有`CHAR`、`VARCHAR`,`TEXT`列上可以创建全文索引。目的为解决`WHERE name LIKE '%word%'`的模糊搜索。 ### **索引规约** > * 业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。 > * 在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。count(distinct left(列名, 索引长度))/count(*)计算区分度 > * SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts最好。 **创建原则** > * 最适合索引的列是出现在`where`子句中的列,或连接子句中的列而不是出现在`select`关键字后的列 > * 索引列的基数越大,索引的效果越好 > * 对字符串进行索引,应该制定一个前缀长度,可以节省大量的索引空间 **注意事项** >[danger] > * 组合索引遵循前缀原则 > * `like`查询时, `%` 不能在前, 可以使用全文索引 > * `column is null` 可以使用索引 > * 如果MySql估计使用索引比全表扫描更慢,会放弃使用索引 > * 如果 `or`前的条件中的列有索引,后面的没有,索引都不会被用到 > * 列类型是字符串,查询时给值加引号,否则索引失效 ### **覆盖索引** * 查询的数据列从索引中就能够获取到,不必从数据表中读取 > 了解覆盖索引之前我们先大概了解一下什么是聚集索引(主键索引)和辅助索引(二级索引)        聚集索引(主键索引):            聚集索引就是按照每张表的主键构造一颗B+树,同时叶子节点中存放的即为整张表的记录数据。            聚集索引的叶子节点称为数据页,聚集索引的这个特性决定了索引组织表中的数据也是索引的一部分。        辅助索引(二级索引):            非主键索引,叶子节点=键值+书签。Innodb存储引擎的书签就是相应行数据的主键索引值。 >* 解释一: 就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖。 > * 解释二: 索引是高效找到行的一个方法,当能通过检索索引就可以读取想要的数据,那就不需要再到数据表中读取行了。如果一个索引包含了(或覆盖了)满足查询语句中字段与条件的数据就叫 做覆盖索引。 >* 解释三:是非聚集组合索引的一种形式,它包括在查询里的Select、Join和Where子句用到的所有列(即建立索引的字段正好是覆盖查询语句\[select子句\]与查询条件\[Where子句\]中所涉及的字段,也即,索引包含了查询正在查找的所有数据)。 >[danger] * 不是所有类型的索引都可以成为覆盖索引。覆盖索引必须要存储索引的列,而哈希索引、空间索引和全文索引等都不存储索引列的值,所以MySQL只能使用B-Tree索引做覆盖索引 >[danger] * 索引是通过二叉树的数据结构来描述的,我们可以这么理解聚簇索引:索引的叶节点就是数据节点。而非聚簇索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块。