最近,我已经将PostgreSQL 8.2.11服务器升级到8.4,以便利用自动清理功能并与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;
产生:
关系| 尺寸 ------------------------------------ + --------- pg_toast.pg_toast_16874 | 89 GB littles00.warmstates | 1095兆字节 ... (20列)
该TOAST表用于一个名为“时间序列”的表,该表保存了大数据记录。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.35秒/2.46微秒过去了21.07秒。
重新索引释放了一些空间(〜1GB)的表。我无法聚集该表,因为磁盘上没有足够的空间用于该进程,并且我正等待完全重建该表,因为我想找出为什么它比我们拥有的等效数据库大得多。
在PostgreSQL Wiki上查询一个查询-“ Show Database Bloat”,这就是我得到的:
current_database | 模式名| 表名| tbloat | wastedbytes | iname | 伊布洛特| 浪费字节 ----------------- + ------------ + ------------------- ------------- + -------- + ------------- + ------------- -------------------- + -------- + -------------- ptrdb04 | somes00 | 时间序列| 1.0 | 0 | idx_timeseries_synchlevel | 0.0 | 0 ptrdb04 | somes00 | 时间序列| 1.0 | 0 | idx_timeseries_localavail | 0.0 | 0 ptrdb04 | somes00 | 时间序列| 1.0 | 0 | idx_timeseries_expirytime | 0.0 | 0 ptrdb04 | somes00 | 时间序列| 1.0 | 0 | idx_timeseries_expiry_null | 0.0 | 0 ptrdb04 | somes00 | 时间序列| 1.0 | 0 | uniq_localintid | 0.0 | 0 ptrdb04 | somes00 | 时间序列| 1.0 | 0 | pk_timeseries | 0.1 | 0 ptrdb04 | somes00 | idx_timeseries_expiry_null | 0.6 | 0 | ?| 0.0 | 0
看来数据库根本不认为该空间是“空”的,但是我只是看不到所有磁盘空间的来源!
我怀疑该数据库服务器决定使用4-5倍的磁盘空间来保存从其他数据服务器提取的相同记录。我的问题是:有没有办法验证行的物理磁盘大小?我想将此数据库上的一行的大小与另一个“健康”的数据库进行比较。
感谢您的任何帮助,您可以提供!
更新1
由于其大小,我最终从转储的架构中重建了表(无法再将其放在另一天)。通过软件同步过程同步数据后,TOAST表约为〜35GB;但是,我只能从该blob列中获得约9GB的存储空间,该存储区应该是最长的值。不确定其他26GB的来源。聚集,真空已满,重新索引无济于事。该postgresql.conf中的本地和远程数据服务器之间的文件正好相同。此数据库是否有任何原因试图在磁盘上存储较大空间的每个记录?
更新2-固定
我最终决定完全从头开始完全重建数据库,甚至可以在系统上重新安装PostgreSQL84软件包。数据库路径被重新初始化,表空间被清除干净。第三方软件同步过程重新填充了表,最终大小为〜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 | 18 GB
somes00 。温暖状态 | 1224 MB
(2 行)
VACUUM VERBOSE ANALYZE timeseries;
INFO:“时间序列”:在58382个页面中的58130个中找到12699个可移动,681961不可移动的行版本 详细信息:无法删除0个死行版本。 有105847个未使用的项目指针。 0页完全为空。 CPU 0.83s / 2.08u秒过去了33.36秒。 INFO:清理“ pg_toast.pg_toast_17269” INFO:扫描索引“ pg_toast_17269_index”以删除2055849行版本 详细信息:CPU 0.37秒/2.92微秒过去了13.29秒。 INFO:“ pg_toast_17269”:在518543页中删除了2055849行版本 详细信息:CPU 8.60秒/3.21微秒过去了358.42秒。 INFO:索引“ pg_toast_17269_index”现在在36786页中包含7346902行版本 详细信息:2055849索引行版本已删除。 10410个索引页已被删除,5124当前可重用。 CPU 0.00s / 0.00u秒经过了0.01秒。 信息:“ pg_toast_17269”:在2378779页中的1257871中找到1286128可移动,2993389不可移动行版本 详细信息:无法删除0个死行版本。 有18847个未使用的项目指针。 0页完全为空。 CPU 26.56s / 13.04u秒过去了714.97秒。 INFO:分析“ fews00.timeseries” INFO:“时间序列”:扫描了680000页中的30000页,其中包含360192个活动行和0个无效行;样本30000行,估计总行821022
重建后唯一显着的差异(磁盘使用率除外)是
INFO:“ pg_toast_17269”:找到1286128可移动的,2993389不可移动的行版本正如@CraigRinger在评论中提到的。不可移动的行数是多少比以前小。
新问题: 其他表会影响另一个表的大小吗?(通过外键等)重建表没有任何作用,但是重建整个数据库证明可以解决该问题。