如何为性能索引字段?
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 >= "some value" AND c.lengthMin < "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 示例。以上是关于如何为性能索引字段?的主要内容,如果未能解决你的问题,请参考以下文章
如何为 CitusDB 的 cstore_fdw 添加索引?