我的问题有两个部分。
我最近从 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 …
我们注意到最近几周我们平台的性能下降,所以我运行了以下命令:
select relname, last_vacuum, last_autovacuum, last_analyze, last_autoanalyze
from pg_stat_user_tables
where relname like 'core_%';
Run Code Online (Sandbox Code Playgroud)
并注意到我们的主桌已经一个多星期没有自动清扫了。所以上周我跑了:
vacuum analyse verbose TABLENAME
Run Code Online (Sandbox Code Playgroud)
这似乎有帮助,但我们现在又遇到了同样的问题。仔细检查后,很多表要么从未被分析过(自动或其他方式),除了vacuum analyse上周手动运行之外,没有一个表被手动清理过,而且很多其他表也没有被自动清理过,充其量是几天前,更糟的是几周前。
我对条款的理解如下:
在 中postgres.conf,autovacuum 属性被注释掉了,但是文档指出这是默认打开的,所以我的假设是即使它被注释掉了,它仍然应该打开吗?
有人可以解释为什么这些表不会被频繁地清理和分析,更具体地说,这些没有更新的值实际上对系统有那么大的影响吗?
信息:Postgres 9.1 操作系统:Ubuntu 12.04
输出
SELECT relname as "Table",
pg_size_pretty(pg_total_relation_size(relid)) As "Size",
pg_size_pretty(pg_total_relation_size(relid) - pg_relation_size(relid)) as "External Size"
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC;
Table | Size | External Size
-----------------+------+---------------
"Primary Table" | 27G | 8232M
Run Code Online (Sandbox Code Playgroud) postgresql performance postgresql-9.1 postgresql-performance
提前很多道歉,但我自己无法找到:
活元组和插入 postgres 统计的元组有什么区别?
有这个帖子,但它没有回答这个问题:pg_stat_get_live_tuples是Representing the number of live [...] rows (tuples) in the table.但什么是“活”?
Postgres文档也不提供答案:
pg_stat_get_live_tuples(oid) Number of live rows in table pg_stat_get_tuples_inserted(oid) Number of rows inserted into table 为什么我的统计数据显示 213,324,422 个插入的元组,但只有 124,510,280 个活动元组?(3,087,919 个死元组)
PG Admin文档对此也不清楚。它还说Tuples Inserted displays the number of tuples inserted into the database within the last week.
我想知道我的数据库中现有条目的总数。这是活动行还是插入行?