【问题标题】:How to use a combined index for expensive aggregating queries?如何使用组合索引进行昂贵的聚合查询?
【发布时间】:2012-08-30 17:32:49
【问题描述】:

我在一个相对较大的表(约 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 部分的同一查询慢多个数量级。

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

【问题讨论】:

  • 您是否检查过索引是否与“解释”一起使用?索引是否包含按此确切顺序排列的列?
  • 你用的是什么引擎? MyISAM 还是 InnoDB?
  • 引擎是 InnoDB。我在所有 4 列上也有一个索引,它必须按特定顺序吗?

标签: mysql performance indexing query-optimization


【解决方案1】:

How MySQL Uses Indexes 中所述:

MySQL 为这些操作使用索引:

[ deletia ]

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

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

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

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

【讨论】:

  • 谢谢,这将查询时间推到了没有where 部分的水平
【解决方案2】:

您可以尝试在第四位索引col_1,但这很大程度上取决于表的结构(即单行的权重)。在col_1 上计算MAX 时,如果没有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 的东西)。

【讨论】:

  • 感谢您的回答。在我的情况下,查询始终是“精确的”,因为 col_2-4 是函数的参数,而 col_1 是该函数运行时创建的时间戳。我想知道的是“函数最后一次使用这些参数运行是什么时候”。
  • 好吧,在这种情况下,如果参数的基数足够小,您也许可以从它们构造一个整数。我怀疑它们是整数格坐标;但如果它们是浮点数,恐怕只有四重索引。很高兴知道这是一种可行的可能性:-)
猜你喜欢
  • 2011-12-19
  • 1970-01-01
  • 2023-03-19
  • 2022-01-16
  • 1970-01-01
  • 2023-02-17
  • 1970-01-01
  • 1970-01-01
  • 2011-01-20
相关资源
最近更新 更多