mysql 中索引使用的存储结构是b+tree
b+tree 和btree 的区别 在于 btree 将数据存储在非叶子节点中,叶子节点中不存数据
而b+tree 是将所有的数据都存在了叶子节点中,非叶子节点中没有数据, 而且b+tree 是双向链表结构 他访问关键字的 顺序是连续性的 不需要再访问上一个节点
聚集索引和非聚集索引
聚集索引是将数据和索引存储再一起的 索引即数据 数据即索引,找到索引所在位置就找到了数据。如主键索引
非聚集索引 再叶子结点上 并没有数据 而是存储了 索引的值和主键的值 通过主键来获取具体的数据
explain 命令使用
在sql 前面加上就可以了
1 先看type 类型 是all 剩下全部不用看 出现all 就是全表扫描 没有命中索引
2看 key 看是否使用索引 null 表示没有
3 rows 表示sql 执行中被扫描到的行数 值越大就越慢 当扫描到的值超过全表的30% 就不会使用索引
索引的类型
1唯一索引和主键索引
主键索引其实就是 聚集索引 每张表中仅有一个主键,可以由多个字段或者单独的字段组成
但是需要满足三个条件
1不能包换null 值
2必须是唯一的
3 必须是自增的
注意:如果表没有主键索引的话 innodb 会使用 表中没有null 值的唯一索引作为主键,如果唯一索引没有的话 会自动生成一个 6字节的 rowid 作为主键
唯一索引:顾名思义 不预序由 重复的值 但是允许由null 值
2覆盖索引
只通过索引就可以查询到返回的值 这样就不需要在回表查询数据 减少了 I/O 操作 这样查询速度就大大加快了
如 name字段上创建的由索引
select name from table where name='123';
或者select id,name from table where name='123';
普通索引中 只记录了 索引的值和 对应数据的主键id 查询的时候 可以直接查询出来 不需要再回表中查询 可以直接返回结果
3前缀索引
像blob text 或者很长的字段 可以使用前缀索引,前缀索引是指定字段前多少位的字符创建的索引,具体多少位看自己定义。 这样索引会更小 查询会更快
但是缺点是 再order by 和 group by 中不能使用该索引
4联合索引
联合索引 又叫 组合索引 和复合索引 是由表中两个 或两个以上的字段组成的索引
但是 使用联合索引 需要遵循 最左原则
5哈希索引
将键值换算成hash值 这里需要注意 hash 索引只能进行等值查询 不能进行范围查询 模糊查询 和排序 但是他检索的时候不需要像b+tree 一样从根节点到叶子节点 逐级查询 值需要一次 hash 算法即可确定到相应的位置
总结
优点
1提高排序效率
2 提高数据检索效率
3提高聚合函数效率
优化
1)先看表是否设计的合理,有没有遵循选取数据类型与简单越小的原则
2)表中的碎片是否整理(一般不会delete 都会设置状态)
3)表的统计信息 是否收集,只有统计信息准确,执行计划才能帮助我们优化sql
4)查看执行计划,检查索引使用的情况,没有索引,考虑创建
5)在创建索引之前,还要查看索引的选择性,来判断是否合适创建索引
什么样的列不适合创建索引
1 选择性低的字段不要创建索引(也就是 字段值比较单一)
2 很少查询的列不要创建索引(项目初期就要确定好)
3 大数据类型字段不要创建索引
4尽量避免不要使用null 应该指定列为 not null (在mysql 中 含有空值的列 很难进行查询优化,他们会使索引的统计信息及比较运算更加复杂,可以使用空字符串代替null)
什么样的列适合创建索引
1)警察被查询的列(一般放在where 后面)
2)经常用于表连接的列
3)经常排序分组的列
使用不到索引的情况
1) 通过索引扫描的行记录超过全表的30% 优化器就不会走索引 而变成全表扫描
2)联合索引中 第一个查询条件不是 最左索引列
3)联合索引中,第一个索引列使用范围查询,只能使用到部分索引(范围查询是指 < + > betweed 和and)
4)联合索引查询条件不是最左前缀列
5)模糊查询 以通配符% 开始(可以考虑放到子查询中)
6)两个单列索引 一个用于检索 一个用于排序 这种情况下 只能使用到一个索引 因为一个sql 语句 最多只能使用一个索引 可以考虑创建联合索引
7)查询字段上面有索引,但是使用了函数运算