我正在执行更新,我需要一个tstzrange变量完全相等。修改了大约 100 万行,查询需要大约 13 分钟。的结果EXPLAIN ANALYZE可以在这里看到,实际结果与查询计划器估计的结果有很大的不同。问题是索引扫描t_range期望返回单行。
这似乎与范围类型的统计信息与其他类型的统计信息的存储方式有关。pg_stats查看列的视图,n_distinct是 -1,其他字段(例如most_common_vals,most_common_freqs)为空。
但是,必须在t_range某处存储统计信息。我在 t_range 上使用 'within' 而不是完全相等的极其相似的更新需要大约 4 分钟才能执行,并且使用了完全不同的查询计划(请参阅此处)。第二个查询计划对我来说很有意义,因为将使用临时表中的每一行和历史表的很大一部分。更重要的是,查询规划器为 上的过滤器预测了近似正确的行数t_range。
的分布t_range有点不寻常。我正在使用这个表来存储另一个表的历史状态,并且对另一个表的更改在大转储中同时发生,因此没有很多不同的t_range. 以下是与 的每个唯一值对应的计数t_range:
t_range | count
-------------------------------------------------------------------+---------
["2014-06-12 20:58:21.447478+00","2014-06-27 07:00:00+00") | 994676
["2014-06-12 20:58:21.447478+00","2014-08-01 01:22:14.621887+00") | 36791
["2014-06-27 07:00:00+00","2014-08-01 07:00:01+00") | 1000403
["2014-06-27 07:00:00+00",infinity) | 36791
["2014-08-01 07:00:01+00",infinity) | 999753
Run Code Online (Sandbox Code Playgroud)
t_range上面distinct的计数是完整的,所以基数是~3M(其中~1M会受到任一更新查询的影响)。
为什么查询 1 的性能比查询 2 …
postgresql performance postgresql-9.3 range-types query-performance
我正在处理复杂的问题,但我会将其简化为这个问题。
我有两张桌子
A [ID, column1, column2, column3]
B [ID, column1, column2, column3, column4]
Run Code Online (Sandbox Code Playgroud)
我想更新第三个:
C [ID, column1, column2,column3]
Run Code Online (Sandbox Code Playgroud)
我正在使用此查询更新另一个第三个表。
UPDATE C
set column1=t.firstTab, column2=t.secondTab, column3=t.thirdTab
from (select A.column1 as firstTab, B.column2 as secTab,
(A.column1 + B.column2) thirdTab
from A, B limit 1; ) as t ;
Run Code Online (Sandbox Code Playgroud)
我有:
UPDATE 0
Run Code Online (Sandbox Code Playgroud)
当我运行此查询时:
select A.column1 as firstTab, B.column2 as secTab, (A.column1 + B.column2) thirdTab
from A, B limit 1;
Run Code Online (Sandbox Code Playgroud)
我得到了结果。我错过了什么吗?
示例数据:http : //sqlfiddle.com/#!15/e4d08/5
我的问题有两个部分。
我最近从 MSSQL 迁移到 Postgres,我们在 MSSQL 世界中创建数据库时所做的一件事是指定数据库和事务日志的初始大小。这减少了碎片并提高了性能,特别是如果事先知道数据库的“正常”大小。
我的数据库的性能随着大小的增长而下降。例如,我处理的工作负载通常需要 10 分钟。随着数据库的增长,这个时间会增加。执行 VACUUM、VACUUM FULL 和 VACUUM FULL ANALYZE 似乎不能解决问题。解决性能问题的是停止数据库,对驱动器进行碎片整理,然后进行 VACUUM FULL ANALYZE 使我的测试性能恢复到原来的 10 分钟。这让我怀疑是碎片化是导致我痛苦的原因。
我在 Postgres 中找不到任何关于保留表空间/数据库空间的参考。要么我使用了错误的术语,因此一无所获,要么在 Postgres 中有一种不同的方法来减轻文件系统碎片。
任何指针?
解决方案
提供的答案有助于确认我开始怀疑的内容。PostgreSQL 将数据库存储在多个文件中,这使得数据库可以增长而不必担心碎片化。默认行为是将这些文件与表数据一起打包,这对很少更改的表有好处,但对经常更新的表不利。
PostgreSQL 利用MVCC提供对表数据的并发访问。在此方案下,每次更新都会创建已更新行的新版本(这可能是通过时间戳或版本号,谁知道?)。旧数据不会立即删除,而是标记为删除。执行 VACUUM 操作时会发生实际删除。
这与填充因子有什么关系?表默认填充因子 100 完全填充表页,这反过来意味着表页内没有空间来保存更新的行,即更新的行将放置在与原始行不同的表页中。正如我的经验所示,这对性能不利。由于我的汇总表更新非常频繁(高达 1500 行/秒),我选择将填充因子设置为 20,即表的 20% 用于插入行数据,80% 用于更新数据。虽然这可能看起来过多,但为更新行保留的大量空间意味着更新行与原始行保持在同一页内,并且在 autovacuum 守护程序运行以删除过时行时表页未满。
为了“修复”我的数据库,我执行了以下操作。
ALTER TABLE "my_summary_table" SET (fillfactor = 20);重新运行我的测试,即使数据库达到我需要的数百万行,我也没有发现性能下降。
TL;DR …