按顺序插入和聚类效果一样吗?

jpm*_*c26 5 postgresql performance

我有一个表,其中包含一些基于其他表的预先计算的数据。(考虑到我必须处理的数据大小,动态计算的计算成本太高。)随着源数据的添加,我将逐步生成。(UPDATE在正常使用中我永远不需要它;部分可能会被删除和重新生成。)该表将相当大。它目前大约有 5000 万行,并且每年都会增长。

对该表的大多数查询都将通过外键 ID 列进行过滤。因此,如果该 ID 的所有行都分组到相同的页面中,它们的性能会更好。我可以通过创建索引和CLUSTER定期调用来保证磁盘上的这种排序,但这显然不太理想,因为它需要某种计划任务,根据使用情况和其他计划任务进行协调等。

但是,由于我以与我想要使用的外键相关的块的形式生成这些数据CLUSTER,因此我可以轻松地ORDER BYINSERT命令中添加一个子句:

INSERT INTO big_table (source_table1_id,a,b,c)
SELECT
   source_table1_id,
   5 /* some formula */,
   /* ... */
FROM source_table1
JOIN source_table2 ON ...
...
WHERE ... /* some condition indicating what needs to be generated */
ORDER BY source_table1_id
Run Code Online (Sandbox Code Playgroud)

这是否会影响磁盘存储顺序,将行分组为接近最小页数?如果确实如此,是否还有其他进程可能会在以后弄乱磁盘顺序?

我目前正在使用 PostgreSQL 9.3,但我想了解更新的版本以及升级。

Erw*_*ter 3

Postgres 在物理上按 INSERTed 顺序写入元组。如果您对新表或没有死元组的表执行此操作,您将获得与CLUSTER在具有与INSERT. CLUSTER稍后以同样的方式写入表的效果会恶化(并且在您从不DELETEUPDATE- 或INSERT破坏所需的顺序时保持完整)。

有些答案集中于后来的写作的影响,而忽略了问题的要点。你的问题的答案基本上是:

是的,按顺序插入确实与聚类具有相同的效果。

基于一些条件:

针对该表的查询将通过外键 ID 列进行过滤。

这意味着您可以一次访问具有相同 FK ID 的行,而不是一系列连续的 ID。那么您所需要的只是按 ID 聚集的行,ID 之间的物理顺序几乎对这些查询没有任何影响。

和:

生成与外键相关的数据块

意思是,“块”包括按顺序具有相同 FK ID 的所有行。没有单独插入同一 FK ID 的其他行。就像是:

INSERT INTO big_table (source_table1_id,a,b,c)
SELECT s1.source_table1_id, ... 
FROM   source_table1 s1
...
WHERE s1.source_table1_id BETWEEN 123 and 125  -- example
ORDER BY s1.source_table1_id
Run Code Online (Sandbox Code Playgroud)

和:

UPDATE在正常使用中我不需要它;部分可以被删除并重新生成。

DELETE是唯一有轻微问题的部分。如果您从不删除其中任何一个,那么您就完成了。ID如果您所说的“部分”是指同时表示的所有行,那么您仍然很好,大多数情况下。在同一事务中删除和插入时,ID 内不存在碎片。(已删除的元组尚未“死亡”,并且不会在同一事务中被覆盖。)

死元组会使表膨胀,随后的插入可以填充物理空洞,这就是碎片开始的地方。死元组造成的膨胀会产生各种累积的不利影响,但对具有相同 FK ID 的行的索引访问基本上不受影响。

但所有这些都与您的问题正交,因为同样的考虑因素也适用于CLUSTER.

考虑社区工具pg_repackpg_squeeze。两者都可以替换CLUSTER,而不需要对表进行排它锁。看:

有关的:


归档时间:

查看次数:

787 次

最近记录:

8 年,9 月 前