【问题标题】:How to Optimize MYSQL in Extra :-Using where; Using temporary; Using filesort如何在 Extra 中优化 MYSQL:-使用 where;使用临时的;使用文件排序
【发布时间】:2018-03-11 02:15:47
【问题描述】:

这个查询的正确索引是什么。

我尝试为这个查询提供不同的索引组合,但它仍在使用 from using tempory , using filesort 等。

总表数据 - 7,60,346

product= '连衣裙' - 总行数 = 122 554

CREATE TABLE IF NOT EXISTS `product_data` (
  `table_id` int(11) NOT NULL AUTO_INCREMENT,
  `id` int(11) NOT NULL,
  `price` int(11) NOT NULL,
  `store` varchar(255) NOT NULL,
  `brand` varchar(255) DEFAULT NULL,
  `product` varchar(255) NOT NULL,
  `model` varchar(255) NOT NULL,
  `size` varchar(50) NOT NULL,
  `discount` varchar(255) NOT NULL,
  `gender_id` int(11) NOT NULL,
  `availability` int(11) NOT NULL,
  PRIMARY KEY (`table_id`),
  UNIQUE KEY `table_id` (`table_id`),
  KEY `id` (`id`),
  KEY `discount` (`discount`),
  KEY `step_one` (`product`,`availability`),
  KEY `step_two` (`product`,`availability`,`brand`,`store`),
  KEY `step_three` (`product`,`availability`,`brand`,`store`,`id`),
  KEY `step_four` (`brand`,`store`),
  KEY `step_five` (`brand`,`store`,`id`)
) ENGINE=InnoDB ;

查询:

SELECT id ,store,brand FROM `product_data` WHERE product='dresses' and 
availability='1' group by brand,store order by store limit 10;

excu..time :-(总共 10 个,查询耗时 1.0941 秒)

解释计划:


可能的键:- step_one、step_two、step_three、step_four、step_five

键:- step_two

ref :- const,const

行:- 229438

额外:-使用 where;使用临时的;使用文件排序

我试过这些索引


Keystep_one (product,availability)

Keystep_two (product,availability,brand,store)

Keystep_three (product,availability,brand,store,id)

Keystep_four (brand,store)

Keystep_five (brand,store,id)

【问题讨论】:

  • 在您的问题中提供SHOW CREATE TABLE product_data 输出。
  • @kuldeepupadhyay 请给我们每个索引组合的时间结果,你提到过
  • @Andy K 是的,先生,我的查询选择第二个索引,他们查询花了 1.0941 秒
  • 他们选择自动第二步,我认为这是最好的组合,但仍然需要更多时间和使用临时,使用文件排序
  • “分组依据”是做什么的?它通常只与聚合函数有关。

标签: mysql sql indexing database-administration


【解决方案1】:

如果没有聚合函数,您的group by clause 就没有任何意义。

如果可以将查询重写为

SELECT id ,store 
FROM `product_data` 
WHERE product='dresses' 
and availability='1' 
order by store limit 10;

然后(product,availability,store) 上的索引将删除所有文件排序。

请参阅 SQLFiddle:http://sqlfiddle.com/#!9/60f33d/2

更新:

SQLFiddle 使您的意图变得清晰 - 您正在使用 GROUP BY 来模拟 DISTINCT。如果是这种情况,我认为您无法摆脱查询中的文件排序和临时表步骤 - 但我也不认为这些步骤应该非常昂贵。

【讨论】:

  • 这与原始请求不匹配,因为它未能执行GROUP BY
  • GROUP BY 在没有聚合的情况下具有DISTINCT 的效果。但是DISTINCT 会偶然发现独特的id
【解决方案2】:

真正的问题不是索引,而是GROUP BYORDER BY 之间的不匹配阻止了对LIMIT 的利用。

这个

INDEX(product, availability, store, brand, id)

将以正确的顺序“覆盖”。但请注意,我已经交换了storebrand...

将查询更改为

SELECT  id ,store,brand
    FROM  `product_data`
    WHERE  product='dresses'
      and  availability='1'
    GROUP BY store, brand    -- change
    ORDER BY store, brand    -- change
    limit  10;

这会将GROUP BY 更改为以store 开头,以反映ORDER BY 排序——这避免了额外的排序。并将ORDER BY 更改为与GROUP BY 相同,以便将两者结合起来。

鉴于这些变化,INDEX 现在可以一直到 LIMIT,从而允许处理只查看 10 行,而不是更大的集合。

任何少于所有这些更改的东西都不会那么有效。

进一步讨论:

INDEX(product, availability,   -- these two can be in either order
      store, brand,      -- must match both `GROUP BY` and `ORDER BY`
      id)   -- tacked on (on the end) to make it "covering"

“覆盖”意味着所有SELECT 的列都在INDEX 中找到,因此无需深入数据。

但是... 整个查询没有意义,因为SELECT 中包含了id。如果您想查找哪些商店有可用的连衣裙,请摆脱id。如果要列出所有可用的连衣裙,请将id 更改为GROUP_CONCAT(id)

【讨论】:

    【解决方案3】:

    对于索引,最好的索引是 step_two。 product 字段用于 where 并且比 availability-field 有更多的变化。

    关于查询的几点说明:

    1. availability='1' 应该是 availability=1,这样可以避免不必要的 int->varchar 转换。
    2. “按品牌分组”不应用作 GROUP BY 仅应在您将聚合函数用作选定列时使用。您想通过小组实现什么目标?

    【讨论】:

    • 是的,先生,我尝试了“SELECT id,brand”,但仍在使用临时文件,使用文件排序。请帮忙
    • 你试图通过组实现什么?
    猜你喜欢
    • 2012-05-23
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-13
    • 2014-01-04
    • 1970-01-01
    • 2016-09-04
    相关资源
    最近更新 更多