分组依据/排序的MySQL索引

bra*_*ido 11 mysql indexing

见下面的查询.我应该在表上创建什么索引,以便查询将使用索引并避免使用临时和filesort?我在这里尝试了许多不同的索引组合和阅读建议,但我似乎无法弄明白.我的解释是说Using Where(没有索引),或者Using Where Using Temporary, Using Filesort

这是一个简化的查询.所有列都是整数.

SELECT c1, Sum(c2) 
FROM table 
WHERE c3 IS NOT NULL 
AND c4 = 2011 
AND c5 = 0 
AND c6 In (6,9,11)  
GROUP BY c1
Run Code Online (Sandbox Code Playgroud)

sri*_*ani 7

这应该对你有帮助.重写您的查询,如下所示:

SELECT c1, Sum(c2) 
FROM table 
WHERE c4 = 2011 
AND c5 = 0 
AND c6 In (6,9,11)
AND c3 IS NOT NULL   
GROUP BY c1
Run Code Online (Sandbox Code Playgroud)

现在在列(c4,c5,c6)上创建一个复合索引,其列为IN THAT ORDER.索引中的列应与WHERE子句中的列的顺序相同.否则索引将无效.这个索引的选择性足够窄,临时表(对于group by)的文件排序应该很快.

将c3移动到查询末尾的原因如下.作为一个例子,让我们假设c3可以取0到100之间的值(或者它可以是NULL).如果运行"IS NOT NULL"查询,则Mysql需要遍历几乎所有B-Tree索引,除了对应于NULL的边.因此,MySQL决定全表扫描比遍历索引中的所有不同路径更容易.另一方面,您将看到如果您的查询是"IS NULL"并且您的索引是(c3,c4,c5,c6),那么Mysql将使用此索引.这是因为在这种情况下,Mysql只需遍历对应于NULL值的索引树部分.

MySQL需要的那种索引在很大程度上取决于所讨论的查询.正如@louis建议的那样,在所有列上创建索引并不是一个好主意!

  • "索引中的列应该与WHERE子句中的列的顺序相同.否则索引将不起作用." 查询优化器不关心`WHERE`子句是如何排序的.`SELECT ... FROM foo WHERE bar = 1 AND baz <5`将具有与`SELECT ... FROM foo WHERE baz <5 AND bar = 1`完全相同的执行计划,并以完全相同的方式使用索引.条件的类型(相等或不等,有选择性或不相等)是重要的,而不是它出现在`WHERE`子句中的位置. (7认同)
  • 我不确定这是真的。根据我的经验,索引定义的顺序很重要,但 where 子句的顺序并不重要。 (3认同)
  • 同意 Shane N - 优化器将在执行前自动为您重新排序 (3认同)