一、索引类型
1.普通索引:这是最基本的索引,它没有任何限制
2.唯一索引:索引列的值必须唯一,但允许有空值
3.主键索引:它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引;
4.组合索引:为了进一步提高效率,将两个或多个字段建到一个索引中
二、索引的区别
普通索引需要回表
三、索引的数据结构(常见模型)
1.哈希表
a.哈希表是一种以键 - 值(key-value)存储数据的结构,我们只要输入待查找的值即 key,就可以找到其对应的值即 Value。哈希的思路很简单,把值放在数组里,用一个哈希函数把 key 换算成一个确定的位置,然后把value 放在数组的这个位置。将不同的输入值通过Hash算法得到长度相同的输出。不可避免地,多个 key 值经过哈希函数的换算,会出现同一个值的情况。处理这种情况的一种方法是,拉出一个链表。
b.哈希表的优点:随机读的速度快
c.哈希表的缺点:适合等值查询,范围查询慢;无法利用索引进行排序;不支持多联合索引的最左前缀原则;如 果有大量重复的键值,效率低,存在哈希碰撞;插入慢。
d.哈希表适合于等值查询的场景
2.有序数组
a.有序数组在等值查询和范围查询场景中的性能就都非常优秀
b.在需要更新数据的时候麻烦,往中间插入一个数据需要挪动后面的记录,所以有序数组索引只适用于静态存储引擎(不需要更改的数据)
3.B+树
a.B+树的叶子节点可以存放整行数据的主键索引,也可以存放主键值的普通索引,
b.B+ 树为了维护索引有序性,在插入新值的时候需要做必要的维护。往中间插入数值时,需要逻辑上挪动后面的数据,空出位置。如果插入的那页已满,这种情况下需要再申请一个新的数据页,然后挪动部分数据过去,这个过程称为页分裂。页分裂不仅影响性能,还影响页的利用率。
c.当相邻两个页由于删除了数据,利用率很低之后,会将数据页做合并。合并的过程,可以认为是分裂过程的逆过程。
三、索引优化
1.覆盖索引:由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优 化手段。
2.最左前缀原作
3.索引下推:mysql5.6以后新加
四、怎么判断你的查询使用了索引
explain 关键字
explain执行结果的字段:
table: 这是重要的列,显示连接使用了何种类型.
type显示的是访问类型,是较为重要的一个指标,结果值从好到坏依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
一般来说,得保证查询至少达到range级别,最好能达到ref。
possible_keys:可能使用了哪个索引在该表中查找行。如果没有使用任何索引,就显示的NULL,可以用于对优化时的索引调整。
key:显示使用的索引,如果没有使用,则显示NULL
key_len:显示的是所使用的索引长度,如果没使用,则是NULL。当然,在使用索引的情况下,索引长度越小。效果越明显。
ref:显示索引的哪一列被使用了,如果可能的话,是一个常数
rows:MYSQL认为必须检查的用来返回请求数据的行数
Extra:关于MYSQL如何解析查询的额外信息。
五、索引失效
1.前导模糊查询:就是模糊查询不能以%开头;
2.如果是组合索引的话,如果不按照索引的顺序进行查找,比如直接使用第三个位置上的索引而忽略第一二个位置上的索引时,则会进行全表查询
3.条件中有or; 应当尽量避免在where语句中使用or连接条件,否则导致引擎放弃使用索引
4.索引无法存储null值,所以where的判断条件如果对字段进行了null值判断,将导致数据库放弃索引而进行全表查询。
单列索引无法储存null值,组合索引无法全储存为null;查询时,采用is null 条件时,不能利用索引,只能通过全表扫描
为什么索引列不能储存null值:索引是有序的。NULL值进入索引时,无法确定其应该放在哪里。
5.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
6.in 和 not in 也要慎用,否则会导致全表扫描,
7. 应尽量避免在索引列上进行函数操作或者运算,这将导致引擎放弃使用索引而进行全表扫描
8.mysql优化器觉的全表扫描效率高,就会放弃索引。