我有一张非常大的桌子,以下代码需要990秒。去完成。 bdate
和itype
已编入索引。我还需要优化/改变什么?
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
答案 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
作为前导列的现有索引。但这意味着查询将需要检查表中的每一行;如果列itype
和EXPLAIN
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
的侵入性会更低。
如果bdate
是DATE
,那么bdate > '2014-10-01'
将取消10月1日;这是故意的吗?