BrM*_*M13 9 postgresql postgresql-8.4
最近,我将 PostgreSQL 8.2.11 服务器升级到 8.4,以便利用 autovacuum 功能并与 30 左右的其他 PGSQL 服务器保持一致。这是由管理硬件的单独 IT 小组完成的,因此我们在任何其他升级上没有太多选择(暂时不会看到 9+)。服务器存在于一个非常封闭的环境中(隔离网络,有限的root权限),运行在RHEL5.5(i686)上。升级后,数据库以每天 5-6 GB 的速度不断增长。通常情况下,整个数据库大约为 20GB;目前,它是~89GB。我们还有其他几台服务器,它们运行等效的数据库,并通过第 3 方应用程序(我无法访问内部工作原理的应用程序)将记录相互同步。其他数据库应该是~20GB。
运行以下 SQL,很明显特定表存在问题,更具体地说,它的 TOAST 表存在问题。
SELECT nspname || '.' || relname AS "relation",
pg_size_pretty(pg_relation_size(C.oid)) AS "size"
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_relation_size(C.oid) DESC
LIMIT 20;
Run Code Online (Sandbox Code Playgroud)
其中产生:
关系 | 尺寸 -------------------------------------+--------- pg_toast.pg_toast_16874 | 89GB somes00.warmstates | 1095 MB ... (20 行)
此 TOAST 表用于名为“timeseries”的表,该表保存大量斑点数据记录。SUM(LENGTH(blob)/1024./1024.)
时间序列中所有记录的A为该列产生约 16GB。应该有什么理由这个表的TOAST表应尽可能大,因为它是。
我已经执行了VACUUM FULL VERBOSE ANALYZE timeseries
,并且真空运行完成,没有错误。
信息:吸尘“pg_toast.pg_toast_16874”
信息:“pg_toast_16874”:在 10448587 页中找到 22483 个可移动的、10475318 个不可移动的行版本
详细信息:0 个死行版本还不能被删除。
不可移动行版本的长度范围为 37 到 2036 个字节。
有 20121422 个未使用的项目指针。
总可用空间(包括可移动行版本)为 0 字节。4944885 页正在或将变为空,包括表末尾的 0。包含 0 个空闲字节的 4944885 个页面是潜在的移动目的地。
CPU 75.31s/29.59u 秒经过 877.79 秒。
信息:索引“pg_toast_16874_index”现在在 179931 页中包含 10475318 个行版本
详细信息:23884 个索引行版本已被删除。
101623 个索引页已被删除,101623 个当前可重用。
CPU 1.35s/2.46u 秒经过 21.07 秒。
REINDEXed 释放了一些空间(~1GB)的表。我无法对表进行 CLUSTER,因为磁盘上没有足够的空间用于该进程,我正在等待完全重建表,因为我想找出为什么它比我们拥有的等效数据库大得多。
从此处的 PostgreSQL wiki 进行查询- "Show Database Bloat",这就是我得到的:
current_database | 架构名称 | 表名 | 膨胀 | 浪费字节 | 姓名 | 膨胀 | 浪费的双字节 -----+------------+----- -------------+--------+------------+------------ --------------------+--------+-------------- ptrdb04 | 少数人 | 时间序列 | 1.0 | 0 | idx_timeseries_synchlevel | 0.0 | 0 ptrdb04 | 少数人 | 时间序列 | 1.0 | 0 | idx_timeseries_localavail | 0.0 | 0 ptrdb04 | 少数人 | 时间序列 | 1.0 | 0 | idx_timeseries_expirytime | 0.0 | 0 ptrdb04 | 少数人 | 时间序列 | 1.0 | 0 | idx_timeseries_expiry_null | 0.0 | 0 ptrdb04 | 少数人 | 时间序列 | 1.0 | 0 | uniq_localintid | 0.0 | 0 ptrdb04 | 少数人 | 时间序列 | 1.0 | 0 | pk_timeseries | 0.1 | 0 ptrdb04 | 少数人 | idx_timeseries_expiry_null | 0.6 | 0 | ? | 0.0 | 0
看起来数据库根本不认为这个空间是“空的”,但我只是不知道所有磁盘空间来自哪里!
我怀疑这个数据库服务器决定使用 4-5 倍的磁盘空间来保存从其他数据服务器提取的相同记录。我的问题是:有没有办法验证一行的物理磁盘大小?我想将此数据库中一行的大小与另一个“健康”数据库进行比较。
感谢您的任何帮助,您可以提供!
更新 1
由于它的大小,我最终从转储的模式中重建了该表(不能再放过它一天)。同步数据后,通过软件同步过程,TOAST表为~35GB;但是,我只能从那个 blob 列中计算出 ~9GB,这应该是最长的值。不确定其他 26GB 来自哪里。CLUSTERed、VACUUM FULLed 和 REINDEXed 无济于事。该postgresql.conf中的本地和远程数据服务器之间的文件正好相同。该数据库是否有任何原因可能会尝试在磁盘上存储具有更大空间的每条记录?
更新 2 - 固定
我最终决定从头开始完全重建数据库 - 甚至在系统上重新安装 PostgreSQL84 软件包。数据库路径被重新初始化并且表空间被清除干净。第 3 方软件同步过程重新填充表,最终大小为~12GB!不幸的是,这绝不有助于解决问题的确切来源。我将观察一两天,看看是否与恢复活力的数据库处理 TOAST 表的方式有任何重大差异,并在此处发布这些结果。
关系大小
ptrdb04=> SELECT nspname || '.' || relname AS "relation",
ptrdb04-> pg_size_pretty(pg_relation_size(C.oid)) AS "size"
ptrdb04-> FROM pg_class C
ptrdb04-> LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
ptrdb04-> WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ptrdb04-> ORDER BY pg_relation_size(C.oid) DESC
ptrdb04-> LIMIT 2;
关系 | 尺寸
-------------------------+---------
pg_toast.pg_toast_17269 | 18GB
somes00.warmstates | 1224 MB
(2 行)
VACUUM VERBOSE ANALYZE timeseries;
信息:“时间序列”:在 68382 页中的 58130 页中找到 12699 个可移除的行版本,681961 个不可移除的行版本 详细信息:尚无法删除 0 个死行版本。 有 105847 个未使用的项目指针。 0 页完全是空的。 CPU 0.83s/2.08u 秒经过 33.36 秒。 信息:吸尘“pg_toast.pg_toast_17269” 信息:扫描索引“pg_toast_17269_index”以删除 2055849 行版本 详细信息:CPU 0.37s/2.92u 秒经过 13.29 秒。 信息:“pg_toast_17269”:删除了 518543 页中的 2055849 行版本 详细信息:CPU 8.60s/3.21u 秒经过 358.42 秒。 信息:索引“pg_toast_17269_index”现在包含 36786 页中的 7346902 行版本 详细信息:删除了 2055849 个索引行版本。 已删除 10410 个索引页,目前可重用 5124 个。 CPU 0.00s/0.00u 秒过去了 0.01 秒。 信息:“pg_toast_17269”:在 2328079 页中的 1257871 中找到 1286128 个可移动的、2993389 个不可移动的行版本 详细信息:尚无法删除 0 个死行版本。 有 18847 个未使用的项目指针。 0 页完全是空的。 CPU 26.56s/13.04u 秒经过 714.97 秒。 信息:分析“fews00.timeseries” INFO:“timeseries”:扫描了 30000 页,共 68382 页,包含 360192 个活行和 0 个死行;样本中有 30000 行,估计总行数为 821022
重建后唯一明显的区别(磁盘使用除外)是
信息:“pg_toast_17269”:发现 1286128 可移动,2993389 不可移动行版本正如@CraigRinger 在评论中提到的那样。不可移动的行数是多少比以前小。
新问题: 其他表可以影响另一个表的大小吗?(通过外键等)重建表没有任何作用,但重建整个数据库证明可以解决问题。
Cra*_*ger 10
这个:
INFO: "pg_toast_16874": found 22483 removable, 10475318 nonremovable row versions in 10448587 pages 22483 removable, 10475318 nonremovable row versions in 10448587 pages
Run Code Online (Sandbox Code Playgroud)
表明潜在的问题是某些东西仍然可以“看到”这些行,因此无法删除它们。
候选人是:
丢失准备好的交易。检查pg_catalog.pg_prepared_xacts
; 它应该是空的。也运行SHOW max_prepared_transactions
; 它应该报告零。
具有开放、空闲事务的长时间运行的会话。在 PostgreSQL 8.4 及更高版本中,这应该只是SERIALIZABLE
事务的问题。检查pg_catalog.pg_stat_activity
了<IDLE> in transaction
会议。
很可能您的客户端在长时间空闲期间无法提交或回滚事务。
如果结果不是这样,我接下来要检查的是对octet_size
感兴趣的表的每一列进行求和。将其pg_relation_size
与桌子及其TOAST
边桌的 进行比较。如果存在很大差异,则不再可见的行可能会占用空间,并且您可能确实存在表膨胀问题。如果它们非常相似,您可以通过汇总每列的八位字节大小、获取最高的“n”值等来缩小空间使用范围。
我不知道为什么它会膨胀。但我做了一些搜索,也许这个链接有一些见解:http://postgresql.1045698.n5.nabble.com/A-154-GB-table-swelled-to-527-GB-on-the-Slony-slave -How-to-compact-it-td5543034.html ...这不是您的确切情况,但也许它足够接近,可以帮助您找到幻影膨胀的底部。
但是,我认为此时压缩该表的唯一方法是将其聚类。由于磁盘空间不足,这是一个问题。
我的建议是:在不同的驱动器上创建一个具有大量额外空间的表空间,然后将问题表分配给该表空间。PostgreSQL 会将表复制到新的表空间(可能会在此过程中对其进行表锁定,因此您需要一个维护窗口)。然后对表进行 VACFULL(清除默认表空间中该表消耗的大部分旧空间)。然后对表进行 CLUSTER,它应该会自行压缩。然后将其放回默认表空间并再次运行 VACFULL(以清除新表空间中未使用的空间)。
归档时间: |
|
查看次数: |
19835 次 |
最近记录: |