✅怎么比较两个索引的好坏?

典型回答

我们都知道,想要看一个 SQL 有没有用到索引,可以通过执行计划来看,并且 MySQL 的索引选择是优化器根据成本预估进行的。也就是说,其实是有可能优化器最终选错索引的。

那么,我们自己在做分析的时候,如何去评判一条 SQL 用到的索引是好是坏呢?如果一个 SQL 可以用到多个索引,那到底应该用哪个更合适呢?

✅为什么MySQL会选错索引,如何解决?

根据上面这篇文章中,我们可以知道,优化器评判一个索引的好坏的依据就是成本,成本低的索引就是好的,成本高的索引就是不好的。

假如说有以下 SQL:

EXPLAIN SELECT * FROM orders WHERE customer_name = "Hollis" and age = 12;

在不考虑索引合并的情况下,他可能会用到customer_name的索引,也可能会用到age的索引。那么,当我们分析两个索引的好坏的时候,有两种非常直观的方式:

  • 1、直接运行一下 SQL,看看他的执行时长
  • 2、通过执行计划分析

运行时长

第一种方式最直接,就是使用指定的索引直接运行一下 SQL,看看他的整体耗时就行了。如:

SELECT * FROM orders FORCE INDEX (customer_name) WHERE customer_name = 'Hollis' AND age = 12;
SELECT * FROM orders FORCE INDEX (age) WHERE customer_name = 'Hollis' AND age = 12;

这里使用 force index进行指定索引。如果是 MySQL 8.0之前,可以用SHOW PROFILES、如果是 MySQL 8.0之后的版本,可以用EXPLAIN ANALYZE来查看 SQL 的耗时情况。具体参考:

✅MySQL 中如何查看一个 SQL 的执行耗时

执行计划

执行计划分析相关的文章我们也介绍过很详细的,如:

✅SQL执行计划分析的时候,要关注哪些信息?

当我们分析两个索引的好坏的时候,一般对比他们的以下信息:

  1. 类型(type)
    • type 字段表示查询的访问类型。理想情况下,类型应该是 const、eq_ref 或 ref,这些类型的查询效率较高。如果是 ALL 或 index,说明进行的是全表扫描或全索引扫描,这通常不是最优的选择。
  2. 扫描行数(rows)
    • rows字段表示查询过程中需要扫描的行数。通常来说,rows 数值越小,说明索引的效果越好,因为这意味着查询过程中需要处理的数据量更少,从而提高了查询的效率。
  3. 过滤率(filtered)
    • filtered 字段表示返回的记录中有多少百分比满足查询条件。过滤率越高,索引的效果越好。
  4. 额外信息(Extra)
    • Extra 字段提供了关于查询的额外信息。理想情况下,不应包含诸如 "Using filesort" 或 "Using temporary" 这样的信息,因为这些操作会降低查询效率。

原文: https://www.yuque.com/hollis666/xkm7k3/yh5zyqc2yt3gshm9