如何为性能索引字段?

Posted

技术标签:

【中文标题】如何为性能索引字段?【英文标题】: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 个子查询,每个子查询都可能需要不同的索引才能有效地满足。 【参考方案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 示例。

以上是关于如何为性能索引字段?的主要内容,如果未能解决你的问题,请参考以下文章

Mysql如何为表字段添加索引?

如何为 MySQL 表添加索引?

如何为 CitusDB 的 cstore_fdw 添加索引?

如何为logstash+elasticsearch配置索引模板?

如何为用打字稿编写的 npm 包指向索引文件

如何为“日期”创建索引?