【问题标题】:How to index the fields for performance?如何为性能索引字段?
【发布时间】:2021-06-05 05:02:27
【问题描述】:

我有一个包含大约 1M 数据的表。我正在执行这个查询,获取记录大约需要 0.9 秒。

SELECT
    c.id, c.tag
FROM
    table as c
WHERE
    c.manufacturer = "some value"
    AND c.power = "some value"
    AND c.bolt = "some value"
    AND c.cylinder = "some value"
    AND c.drive = "some value"
    AND c.minSize <= "some value"
    AND c.speedMin = "some value"
    AND c.lengthMin  >= "some value"
    AND c.widthMin >= "some value"
    
GROUP BY c.manufacturer, c.class, c.version, c.minSize, c.bolt, c.innerBoltF, c.innerBoltR, c.body, c.drive, c.lengthMin, c.lengthMax, c.widthMin, c.widthMax, c.seats, c.speedMax, c.speedMin

我有索引列manufacturer, power

EXPLAIN 给我以下结果:

SIMPLE c index_merge 制造商,电源制造商,电源 77,4 57 使用 intersect(manufacturer,power);使用哪里;使用临时的;使用文件排序

在某些情况下,我可能会查询速度、长度和宽度的范围

例如c.lengthMin &gt;= "some value" AND c.lengthMin &lt; "some value"

我不确定 0.9s 是否是一个不错的速度。

但就我而言,我必须使用 UNION ALL。假设上面的查询是基于某些条件的 Query1,我的最终查询看起来像

Query1 UNION ALL Query2 UNION ALL Query3 ....

因此,对于大约 100 个 UNION ALL 条件,单次执行大约需要 3-5 分钟,这比较慢。我必须使用 UNION ALL,因为我需要知道根据条件执行的是哪一列。

是否可以添加更多索引以更快地执行查询?我应该为哪些列编制索引?

请帮忙。

【问题讨论】:

  • 您没有使用任何聚合函数。为什么你使用 group by 子句?
  • @AmitVerma 你的意思是使用 DISTINCT 而不是 GROUP BY 吗?
  • 我在问为什么使用 group by 子句。
  • @Strawberry 我用解释更新了问题
  • 您在滥用 MySQL 臭名昭著的非标准 GROUP BY 实现。请read this。而且,100 个 UNION ALL 子句意味着 100 个子查询,每个子查询都可能需要不同的索引才能有效地满足。

标签: mysql indexing query-optimization


【解决方案1】:

INTERSECT 提示您有两个单列索引,而两列的“复合”索引会更好。

    c.manufacturer = "some value"
AND c.power = "some value"
AND c.bolt = "some value"
AND c.cylinder = "some value"
AND c.drive = "some value"
AND c.speedMin = "some value"

其中哪 3 个可能是最有选择性的?然后用这 3 列创建一个索引。这将 帮助 WHERE 子句,从而加快查询速度。 (“3”是任意的。)

我怀疑您允许用户指定列的任意子集?如果是这样,则选择最常使用“=”测试的 6 对列,并创建 2 列复合索引。 (“6”和“2”是任意的。)

联合中的 100 个选择可能非常低效。请详细说明查询的目标;可能是替代解决方案。向我们展示一个示例(但在大约 3 个 Union 项之后停止。

当你有一个“范围”(例如,“last放在复合索引中。并且在索引中包含 2 个范围列是没有用的。也就是说,放任意数量的“=”列,然后最多放1个“范围”列。

【讨论】:

  • 感谢您的解释。关于 UNION ALL 的目的,我有来自同一张表的select Id, 'c1' from tbl where condition1 union all select Id, 'c2' from tbl where conditions ...。有没有其他选择?我不能运行查询 100 次,这更慢,所以我尝试使用联合运行一次。
  • @SS - 这些是不同的条件吗?你想要“非此即彼”,而不是“两者兼而有之”?
  • 是的,这些条件与数组不同。
  • 你可以在 WHERE 中使用 OR。
  • 要扩展建议,您还可以根据复合条件交替选择中的列,这将按从左到右的顺序优先。 CASE WHEN (power,bolt) = (3,17) THEN c1 WHEN (power,drive) = (11,4) THEN c2 END 参见db-fiddle 示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-18
  • 1970-01-01
  • 2021-08-16
  • 2018-06-02
相关资源
最近更新 更多