【问题标题】:Mysql multiple column index using wrong indexMysql多列索引使用错误的索引
【发布时间】:2019-01-24 23:24:18
【问题描述】:

我在 products 表上有索引:

  1. 初级
  2. products_gender_id_foreign
  3. products_subcategory_id_foreign
  4. 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 products NULL ref products_gender_id_foreign,products_subcategory_id... products_subcategory_id_foreign 5 const 2 2.50 使用索引条件;使用哪里;使用文件排序

【问题讨论】:

  • 您的行数似乎很少,所以具体的索引并不重要。
  • 任何query-optimization 问题都应包含SHOW CREATE TABLE <name> 的输出
  • 虽然很难阅读您的索引名称,但created_at 可能会添加到索引的末尾。如果字段是数字,请尽量不要引用数字。
  • 你需要给created_at添加一个索引来避免filesort
  • @LuisMuñoz - 添加created_at不会避免文件排序除非索引还处理所有的@987654328 @.

标签: mysql sql optimization indexing query-optimization


【解决方案1】:

正如MySQL documentation 中所述,在某些情况下可以忽略索引。由于已经使用了一个索引,因此可能适用于您的情况的是:

  • 您正在将索引列与常量值进行比较,而 MySQL 具有 计算(基于索引树)常量也覆盖 表的大部分,并且表扫描会更快。看 第 8.2.1.1 节,“WHERE 子句优化”。

  • 您正在使用低基数的键(许多行与键匹配 值)通过另一列。在这种情况下,MySQL 假设由 使用密钥它可能会进行许多密钥查找和一个表 扫描会更快。

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

【讨论】:

    【解决方案2】:

    正如我所说的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,从而不必获取大量行并对其进行排序。

    至于你关于它选择哪个索引的实际问题......可能一个不充分索引的基数比另一个更好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-12
      • 1970-01-01
      • 1970-01-01
      • 2011-03-04
      • 1970-01-01
      • 1970-01-01
      • 2019-02-09
      相关资源
      最近更新 更多