作者:一个有点自卑的小孩 | 来源:互联网 | 2023-09-25 21:01
巧妙的使用Explain看一条SQL语句的性能,可以使用explain关键字查看语句性能,这里说一下其中的type字段的部分含义,all,即全表扫描,说明这个SQL语句没有使用到索
巧妙的使用 Explain
看一条 SQL 语句的性能,可以使用 explain
关键字查看语句性能,这里说一下其中的 type
字段的部分含义,
all,即全表扫描,说明这个 SQL 语句没有使用到索引,有可能是表本身没有创建索引,也可能是因为 SQL 语句导致没有使用索引
range,说明使用的是有范围的索引扫描,性能优于 index
index,这里说明使用了索引,这种情况下,如果 extra 列中的值为 Using index,这种情况是索引覆盖,索引覆盖的意思是,我们想要查询的数据,索引中已经都存在啦,这种情况下就不需要再回表取数据了
ref,说明条件列使用了索引,但是不是主键和 unique,所以这里即使使用了索引,索引值不唯一,有重复的情况
eq_ref,相对于 ref 来说就是使用的是唯一索引,对于每个索引键值,只有唯一的一条匹配记录
const/system,单表中最多只有一条匹配行,查询起来非常迅速,所以这个匹配行中的其他列中的值可以被优化器在当前查询中当做常量来处理。例如根据主键或者唯一索引进行的查询
index_merge,说明使用了 MySQL 的索引合并的优化方法,当使用合并索引的时候,就需要检查一下我们所创建的索引是否为多个单列索引
如何有效的优化索引
使用索引的时候,索引必须作为独立的列出现
作为独立的列的意思是,索引不能作为表达式的一部分,也不能作为函数的参数出现,否则索引会失效,原因是 MySQL 无法自动解析表达式以及参数,所以也就无法使用索引了,索引失效还有以下几种情况:
条件中使用 is null
或者 is not null
会导致索引失效,原因是索引中不会存储 null
使用 %like
,因为 MySQL 是左匹配,使用模糊查询时如果以%
开头会导致全表查询
使用多列索引的时候,如果索引顺序不是建立索引的顺序,或者跳过第一个索引直接使用后面的索引,也会导致索引失败,原因依然是 MySQL 是左匹配~
条件中包含or
时,只有所有列都是单独索引时才会使用索引
如何创建有效的索引
如果需要索引很长的字符串,此时需要考虑前缀索引
计算该列完整列的选择性,使得前缀选择性接近于完整列的选择性
前缀索引即选择所需字符串的一部分前缀作为索引,这时候,需要引入一个概念叫做索引选择性,索引选择性是指不重复的索引值与数据表的记录总数的比值,可以看出索引选择性越高则查询效率越高,当索引选择性为1时,效率是最高的,但是在这种场景下,很明显索引选择性为1的话我们会付出比较高的代价,索引会很大,这时候我们就需要选择字符串的一部分前缀作为索引,通常情况下一列的前缀作为索引选择性也是很高的
如何选择前缀
使用多列索引
选择合适的索引列顺序
覆盖索引
使用索引扫描来做排序
压缩索引
减少重复、冗余以及未使用的索引
MySQL 的唯一限制和主键限制都是通过索引实现的,所以不需要在同一列上增加主键、唯一限制再创建索引,这样是重复索引
再举个例子,如果已经创建了索引(A,B),那么再创建索引(A)的话,就属于重复索引,因为 MySQL 索引是最左前缀,所以索引(A,B)本身就可以使用索引(A),但是创建索引(B)的话不属于重复索引
尽量减少新增索引,而应该扩展已有的索引,因为新增索引可能会导致 INSERT、UPDATE、DELETE 等操作更慢
可以考虑删除没有使用到的索引,定位未使用的索引,有两个办法,在 Percona Server 或者 MariaDB 中打开 userstates 服务器变量,然后等服务器运行一段时间后,通过查询 INFORMATION_SCHEMA.INDEX_STATISTICS 就可以查询到每个索引的使用频率
索引和锁
减少索引和数据碎片
首先我们需要了解一下为什么会产生碎片,比如 InnoDB 删除数据时,这一段空间就会被留空,如果一段时间内大量删除数据,就会导致留空的空间比实际的存储空间还要大,这时候如果进行新的插入操作时,MySQL 会尝试重新使用这部分空间,但是依然无法彻底占用,这样就会产生碎片
产生碎片带来的后果当然是,降低查询性能,因为这种情况会导致随机磁盘访问
可以通过 OPTIMIZE TABLE 或者重新导入数据表来整理数据
总结
数据库的索引这部分要讲的话实在是太多了~绝大部分情况都需要结合实际情况,如果我们可以更多的了解数据库索引本身的一些原理,那么对于优化会有一些帮助~巧妙地使用 explain 分析自己所写的 SQL 语句,可以更好的进行优化。