Mysql多列索引使用错误的索引

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql多列索引使用错误的索引相关的知识,希望对你有一定的参考价值。

我在产品表上有索引:

  1. products_gender_id_foreign
  2. products_subcategory_id_foreign
  3. idx_products_cat_subcat_gender_used(多列索引)

查询:

select `id`, `name`, `price`, `images`, `used`
from `products`
where `category_id` = '1' and
      `subcategory_id` = '2' and
      `gender_id` = '1' and
      `used` = '0'
order by `created_at` desc
limit 24 offset 0

题:

为什么mysql使用索引

products_subcategory_id_foreign

代替

idx_products_cat_subcat_gender_used(多列索引)

这里解释:

1 SIMPLE产品NULL ref products_gender_id_foreign,products_subcategory_id ... products_subcategory_id_foreign 5 const 2 2.50使用索引条件;用在哪里;使用filesort

答案

正如在MySQL documentation中所解释的那样,在一些环境中可以忽略指数。那些可以适用于你的情况,因为一个索引已经被使用,是:

  • 您正在将索引列与常量值进行比较,并且MySQL已经计算(基于索引树)常量覆盖了表的一部分,并且表扫描会更快。请参见第8.2.1.1节“WHERE子句优化”。
  • 您正在使用具有低基数的键(许多行与键值匹配)通过另一列。在这种情况下,MySQL假设通过使用密钥,它可能会执行许多密钥查找,并且表扫描会更快。

我的猜测是category_id的值不够稀疏

另一答案

正如我所说的here,这个

where `category_id` = '1' and
      `subcategory_id` = '2' and
      `gender_id` = '1' and
      `used` = '0'
order by `created_at` desc
limit 24 offset 0

需要一个5列的综合指数:

INDEX(category_id, subcategory_id, gender_id, used,  -- in any order
      created_at)

到达LIMIT,从而不必获取大量行并对它们进行排序。

关于你选择哪个指数的实际问题......可能一个指数不足的基数比另一个指数要好。

以上是关于Mysql多列索引使用错误的索引的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 中的多列索引如何工作?

mysql单列索引多列索引的使用

Mysql多列索引经典案例

聊聊mysql的多列组合查询

MySQL中多列索引的字段顺序是不是重要

mysql索引的艺术 单列索引与多列索引的区别