如何使用组合索引进行昂贵的聚合查询?

时间:2012-08-30 17:32:50

标签: mysql performance indexing query-optimization

我在一个相对较大的表(约2000万行)上使用以下查询:

SELECT 
    MAX(`col_1`) 
FROM `table` 
WHERE  
    col_2 = X AND
    col_3 = Y AND
    col_4 = Z

我在列col_2,col_3和col_4上有一个组合索引,在col_1上有一个单独的索引,但查询仍然比没有WHERE部分的同一查询慢几个数量级。

如何使用索引来提高性能呢?

2 个答案:

答案 0 :(得分:1)

您可以尝试在第四个位置索引col_1,但很大程度上取决于表格的结构(即单个行的权重)。在MAX上计算col_1时,如果没有WHERE,则可以通过索引立即获取信息(只需将其保持在左侧,就像它一样)。

添加WHERE,不再如此。您的查询可能已经过优化。可能(可能)通过了解X,Y和Z的类型和分布来进一步改进。

(一个愚蠢的例子:说col_2col_3col_4已知在范围内(-255,+ 255)。然后您可以考虑添加额外的非正规化列保持(((col_1+255)*512+(col_2+255))*512+(col_3+255))并对其进行索引和col_1。甚至可能基于该索引进行聚类。如果你能找到一个结果相当小的内射函数,这是值得的。数据类型,你经常在X,Y和Z上运行“精确”查询,即没有WHERE col_2 BETWEEN X1 AND X2的东西。

答案 1 :(得分:1)

正如How MySQL Uses Indexes所述:

  

MySQL使用索引进行这些操作:

     

[ deletia ]

     
      
  • 要查找特定索引列 key_col MIN()MAX()值。这是由预处理器优化的,该预处理器会检查您是否在索引中 WHERE key_part_N = constant 之前的所有关键部分上使用key_col。在这种情况下,MySQL对每个MIN()MAX()表达式执行单个键查找,并将其替换为常量。如果所有表达式都替换为常量,则查询立即返回。例如:

    SELECT MIN(key_part2),MAX(key_part2)
    FROM tbl_name WHERE key_part1=10;
  •   

因此,当您应用过滤器时,MySQL无法使用您在col_1上定义的简单索引来查找MAX(col_1):它必须扫描所有匹配的行(尽管它可以在降序中执行此操作)通过对该简单索引进行排序,col_1的顺序),如查询的EXPLAIN输出所示。

您应该使用(col_2, col_3, col_4, col_1)上的索引。