引言
最简单的数据查询方式是全表扫描,找出符合条件的数据。
索引的设计灵感来源于字典,根据关键信息可以快速定位。
为什么要使用索引
索引能够避免全表扫描,提升检索效率。
什么样的信息能成为索引
主键,唯一键等能够让数据具备一定区分度的字段。
索引的数据结构
主流使用 B+
树,也有一部分数据库索引使用 Hash
索引、BitMap
。
Hash 索引的缺点
-
Hash
索引仅能满足=
和IN
查询,无法实现范围查询。 -
Hash
索引值的大小关系并不一定和Hash
运算前的大小关系完全一样,数据库无法利用索引的数据来避免任何排序运算。 - 对于组合索引,
Hash
索引在计算Hash
值的时候是组合索引键合并后再一起计算Hash
值的,不是单独计算Hash
值,所以不能利用部分索引键查询。 - 不同数据可能存在相同的
Hash
值,所以不能避免表扫描。 - 遇到大量
Hash
值相等的情况后性能会降低。
密集索引和稀疏索引的区别
密集索引:叶子节点保存了整条数据记录。密集索引决定了表的物理排列顺序,一个表只有一个物理排列顺序,所以一个表只能创建一个密集索引。
稀疏索引:叶子节点只保存了键值以及该行数据记录的地址 / 主键。
InnoDB
如果一个主键被定义,则该主键作为密集索引。
如果没有主键被定义,该表的第一个唯一非空索引则作为密集索引。
若不满足以上条件,InnoDB
内部会生成一个隐藏主键(密集索引)。
非主键索引存储相关键位和其对应的主键值,包含两次查找。
MySQL
InnoDB
中,主键使用密集索引,辅助键使用稀疏索引。稀疏索引中存储的是数据的主键。
MyISAM
中,主键与辅助键都是用稀疏索引,存储的是数据的地址。
如何定位并优化慢查询 SQL
整体思路:
- 根据慢日志定位慢查询
SQL
- 使用
explain
等工具分析SQL
- 修改
SQL
或尽量让SQL
走索引
慢日志:MySQL
的慢查询日志是 MySQL
提供的一种日志记录,它用来记录在 MySQL
中响应时间超过阀值的语句。
设置:
键 | 配置 | 描述 |
---|---|---|
long_query_time | 1 | 超过 1s 被记录为慢查询 |
slow_query_log | ON | 开启慢查询日志 |
slow_query_log_file | xxx.log | 慢查询日志文件 |
联合索引的最左匹配原则的成因
建立联合索引:index_area_title
。
SELECT * FROM person_info WHERE area = 'TIANJIN' AND title = 'YUNZHI'
,走索引。可以乱序。
SELECT * FROM person_info WHERE area = 'TIANJIN'
,走索引。
但是,SELECT * FROM person_info WHERE title = 'YUNZHI'
,不走索引。
-
MySQL
会一直向右匹配直到遇到范围查询(>/</between/like)
就停止匹配。比如a = 3 and b = 4 and c > 5 and d = 6
,如果建立(a, b, c, d)
顺序的索引,d
就是用不到索引的;如果建立(a, b, d, c)
的索引则都可以用到。 -
=
和IN
可以乱序,比如a = 1 and b = 2 and c = 3
建立(a, b, c)
索引可以任意顺序,MySQL
的查询优化器会优化成索引可以识别的形式。
原因
MySQL
创建复合索引的规则是首先对复合索引的最左边,也就是索引的第一个字段进行排序,再第一个字段的基础上,再对索引上第二个字段进行排序。
第一个字段是绝对有序的,第二个字段就是无序的了,因此直接使用第二个字段判断是用不到索引的。
索引是建立得越多越好吗
- 数据量小的表不需要建立索引,建立会增加额外的开销。
- 数据变更需要维护索引,因此更多的索引意味着更多的维护成本。
- 更多的索引也意味着更多的空间。