无法使用索引的情况

  1. 索引的选择性太差的时候,不会用到索引,也就是重复的太多了,或者查询的范围太大了(个人经验结果大于总数的25%),导致mysql的查询优化器认为,直接对表进行全表扫描还更快,所以执行计划中干脆就不使用索引
  2. <>或者not in,无法使用索引
  3. is null会使用索引,is not null不会使用索引
  4. 联合索引要遵循左前缀原则
  5. 前缀索引要遵循左前缀原则
  6. 对索引列进行计算,或者使用函数进行加工
  7. 在WHERE子句中,如果在OR前的条件列是索引列,而在OR后的条件列不是索引列,那么索引会失效。

索引优化排序

单字段排序

假设idx_uid_sid(uid,source_id)复合索引

  1. 当排序出现了索引左侧列的时候,则可以使用索引进行排序
  2. 左侧字段单字段排序时候,索引可以升降序排序
explain select * from t_content where uid < 1000 order by uid desc;

当排序为索引右侧列的时候,就用到文件排序,using filesort,从排序的角度来看速度是比较慢的

explain select * from t_content where uid < 1000 order by source_id desc;

多字段排序

假设idx_uid_sid(uid,source_id)复合索引:
这个时候,左侧字段必须是升序,且字段的前后顺序不允许

-- 可以索引排序
explain select * from t_content where uid < 1000 order by uid,souce_id asc;
-- 左侧字段不是升序排序,无法利用索引进行排序
explain select * from t_content where uid < 1000 order by uid desc,souce_id asc;
-- 不可以索引排序,是file sort,因为uid顺序不是索引顺序
explain select * from t_content where uid < 1000 order by source_id,uid asc;

删除冗余索引

percona-toolkit工具

由于开发的时候,大家经常会各建个的索引,导致索引冗余,会占用磁盘空间,对表插入和更新操作的时候,会大量索引的重算,

  1. pt-duplicate-key-checker是percona-toolkit工具包中的实用组件,这个工具可以在语法层面上分析冗余索引
  2. 它可以帮助你检测表中重复的索引或者主键

首先下载:https://www.percona.com/downloads/percona-toolkit/LATEST/,然后选择对应的版本,直接解压到指定的目录即可
输入以下命令,就可以生成报表:

/usr/local/bin/pt-duplicate-key-checker --host=192.168.1.106 --user='mysql' --password='123456' --databases=test --tables=curs

sql查看索引运行情况

索引使用状况统计

SELECT
    object_type,
    -- 数据库名称
    object_schema,
    -- 表的名称
    object_name,
    -- 索引的名称,如果为null的话说明是进行全表扫描,要排查sql
    index_name,
    -- 索引在计算过程中读取了多少行
    count_read,
    -- 查询得到的结果是多少行
    count_fetch,
    -- 通过索引所操作的新增修改删除的数量
    count_insert,
    count_update,
    count_delete
FROM
    -- 从索引的角度,看下磁盘io的处理情况,相当于日志的统计表
    performance_schema.table_io_waits_summary_by_index_usage
ORDER BY
    -- 利用索引查询的总时间,可以看那个索引用的最多
    sum_timer_wait DESC;

如果允许一段时间后,查询到的索引统计值都为0,说明索引没有被使用,可以删除

减少表和索引碎片

window系统中有一个碎片扫描和整理程序,它的作用是让我们的系统的文件更有效的组织在一起,让我们的io更加的流畅。在mysql中也存在这个问题,无论是表还是索引,在数据进行频繁的新增修改删除以后,往往都需要重新组织,但是在组织的过程中,必不可少的会有一些空间上的浪费,以及数据组织上的不合理的地方,如下两个命令就是用于解决这个问题的:

analyze table 表名

这个是索引重新统计。mysql底层对数据状况的重新统计,这个很重要,查询优化器优化sql是基于这个统计信息,对于innodb这种存储引擎,这种统计信息是一个估算值,频繁修改数据后,可能会导致统计信息不准确,隔一段时间有必要重新计算这些统计信息

optimize table 表名

这个是优化表空间,释放表空间。innodb的聚集索引,数据在磁盘中是顺序排列的,但是当数删除等操作的是,就会导致数据数据之间有间隙,并且无法被利用,这个命令就可以重新组织数据,重新利用这些间隙,查询效率就会提高。
执行这条命令会锁表,所以执行这条命令,要在维护期间执行,否则造成io阻塞。而且数据量很大的是,执行时间会很长。

最后修改:2023 年 12 月 30 日
如果觉得我的文章对你有用,请随意赞赏