-2 postgresql performance postgresql-performance
你能解释一下,我如何优化这样的选择:
SELECT * FROM calls WHERE id_temp % 5 = 0 LIMIT 300000
Run Code Online (Sandbox Code Playgroud)
此选择正在处理具有 5000 万条记录的表。
非常感谢,祝你有美好的一天。
假设id_temp没有一些高度倾斜的(有利于您的查询)分布,我看不到任何优化此查询的方法。
您需要 300K 行,并且一行匹配条件的几率约为 1/5(在非偏斜假设下),因此它将从表中读取大约 150 万行,直到找到 300K 匹配项。
即使您有一个索引id_temp并且可以更快地找到 300K 匹配项,仍然必须从表中读取 300K 行(如您所见SELECT *),并且由于它们将与不匹配的行交错,因此它仍在继续读取与没有索引时相同数量的磁盘页面。
我认为你最好的机会 - 除了提高磁盘 I/O 性能 - 是如果你id_temp % 5以某种方式使用表达式对表进行分区- 但我会把这留给 Postgres 专家。也许其他一些魔法效果会更好。
另一个想法是将id_temp % 5表达式作为第一列的索引,但这实际上是复制整个 50M 行表:
CREATE INDEX id_temp_modulo_5_idx
ON calls
( (id_temp % 5), id_temp, --- all the other columns as well --- );
Run Code Online (Sandbox Code Playgroud)
或者如果您只需要= 0条件并且永远不需要=1(或 2, 3,4),则使用部分索引。与上面的相比,这将节省大约 80% 的空间:
CREATE INDEX id_temp_modulo_5_equals_0_idx
ON calls
( (id_temp % 5), id_temp, --- all the other columns as well --- )
WHERE
(id_temp % 5 = 0) ;
Run Code Online (Sandbox Code Playgroud)