MySQL查询需要很长时间才能在巨大的表上返回

时间:2015-04-22 19:13:49

标签: mysql database performance indexing

我有一张非常大的桌子,以下代码需要990秒。去完成。 bdateitype已编入索引。我还需要优化/改变什么?

SELECT s, count(*) as total
FROM  `mt_ex_15` 
WHERE bdate > '2014-10-01' and bdate < '2014-11-01'
and itype = '3'
group by s
order by total desc

编辑:以下是EXPLAIN

id  select_type table   type    possible_keys   key key_len ref rows    Extra   
1   SIMPLE  mt_ex_15    ref itype,bdate,s   itype   2   const   44157686    Using where; Using temporary; Using filesort    

编辑:我认为我需要优化我的数据库或my.cnf,因为即使以下查询也需要40秒。

SELECT count(*) as total
FROM  `mt_ex_15` 
WHERE bdate > '2015-02-01' and bdate < '2015-03-01'

以下是解释:

 id     select_type     table   type    possible_keys   key     key_len     ref     rows    Extra   
1   SIMPLE  mt_ex_15    range   bdate   bdate   3   NULL    4494019     Using where; Using index

3 个答案:

答案 0 :(得分:1)

对于此查询:

SELECT s, count(*) as total
FROM  `mt_ex_15` 
WHERE bdate > '2014-10-01' and bdate < '2014-11-01' and itype = '3'
group by s
order by total desc

最佳指数为mt_ex_15(itype, bdate, s)。引擎应该能够充分利用where子句的索引。此外,这是覆盖索引,因此不需要触及此查询的原始数据。

如果你有一个所有可用的列表&#34; s&#34;值,您可以将其作为相关子查询执行:

select s.*,
       (select count(*)
        from mt_ex_15 m
        where m.s = s.s and m.itype = 3 and m.bdate > '2014-10-01' and m.bdate < '2014-11-01'
       ) total
from s
having total > 0 -- using a convenient MySQL extension
order by total desc;

此查询的最佳索引是mt_ex_15(s, itype, bdate)

注意:如果itype实际上是一个整数,则应删除常量周围的引号。它们具有误导性。

答案 1 :(得分:0)

使用EXPLAIN查看执行计划。

缺乏关于桌子的任何信息,我们真的只是在猜测。

我尝试达到这样的指定结果:

CREATE INDEX `mt_ex_15_IX1` ON `mt_ex_15` (`itype`,`s`,`bdate`);

SELECT t.s
     , SUM(t.bdate > '2014-10-01' AND t.bdate < '2014-11-01') AS `total`
  FROM `mt_ex_15` t
 WHERE t.itype = '3'
 GROUP BY t.s
HAVING `total` > 0
 ORDER BY t.s DESC

比较此EXPLAIN输出和原始遗嘱(可能),显示两个查询使用不同的执行计划。

<强>后续

使用合适的索引,MySQL可以避免昂贵的&#34;使用filesort&#34;操作。我上面推荐的索引会使itype列上的索引冗余,并且可以删除该索引。 (任何使用该索引的查询都可以使用新索引,因为itype是前导列。

新索引的建议基于查询...... itype上的等式谓词(将该列作为前导列),然后是s,因为那里有GROUP BY bdate 1 +}在该列上。在索引中包含EXPLAIN列意味着可以从索引中满足查询,而无需查找基础数据页。

我们期待s输出&#34;额外&#34;列显示&#34;使用索引&#34;,而不显示&#34;使用filesort&#34;。

如果无法添加索引,那么您最好避免使用&#34;使用filesort&#34;将使用列bdate作为前导列的现有索引。但这意味着查询将需要检查表中的每一行;如果列itypeEXPLAIN SELECT t.s , SUM(t.itype = '3' AND t.bdate > '2014-10-01' AND t.bdate < '2014-11-01') AS `total` FROM `mt_ex_15` t GROUP BY t.s HAVING `total` > 0 ORDER BY t.s DESC 未包含在索引中,那么这意味着对表中的每一行进行索引查找。但是,这可能会更快。检查EXPLAIN的输出以查询此查询:

aPropertyAlpha: function() { 
  return this.get('aProperty')==='alpha'; 
}.property('aProperty')

答案 2 :(得分:0)

GROUP BY s ORDER BY total - 你至少有一个“filesort”。根据各种不同,排序实际上可能在RAM中。

一个离谱的建议:

  • 更改为GROUP BY itype, s - GROUP BY中不必要的字段可能会导致更好的EXPLAIN。
  • INDEX(itype, s, bdate) - 按此顺序

如果您使用的是MySQL 5.6.16或更高版本,ALTER TABLE ... ALGORITHM = INPLACE的侵入性会更低。

如果bdateDATE,那么bdate > '2014-10-01'将取消10月1日;这是故意的吗?