PostgreSQL初始数据库大小


12

我的问题分为两部分。

  1. 有没有一种方法可以在PostgreSQL中指定数据库的初始大小?
  2. 如果没有,当数据库随着时间增长时如何处理碎片?

我最近从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%用于更新数据。尽管这看起来可能过多,但为更新的行保留的大量空间意味着更新的行与原始行位于同一页面内,并且在自动清理守护程序运行以删除过时的行时,表页面未满。

为了“修复”我的数据库,我做了以下工作。

  1. 将摘要表的填充因子设置为20。您可以在创建时通过将参数传递给CREATE TABLE或在事后通过ALTER TABLE来实现。我发出了以下plpgsql命令:ALTER TABLE "my_summary_table" SET (fillfactor = 20);
  2. 发出VACUUM FULL,因为这将写入表文件的全新版本,因此,暗含了使用新的填充因子写入新的表文件的情况

重新运行测试,即使数据库足够大以容纳数百万行,我也看不到性能下降。

TL; DR-不是文件碎片造成的,而是表空间碎片造成的。通过调整表格的填充因子以适合您的特定用例,可以缓解这种情况。


我怀疑这是文件大小调整操作。我的猜测是,维护索引会降低插入速度。有这方面的PG邮件列表上目前的讨论(尽管没有一个解决方案):postgresql.1045698.n5.nabble.com/...
a_horse_with_no_name

Answers:


4
  1. 唯一接近的是使用--with-segsize开关编译服务器时,如果您的表占用的空间超过演出的空间,并且文件系统可以处理超过演出的单个文件,那么这可能会有所帮助。如果插入20个演出,如果不使用此开关,则必须创建20个文件。如果您的文件系统可以通过演出来处理文件,则可以将其设置为较大的值,最有可能看到一些好处,最坏的情况是得到小的好处。

  2. 看看CLUSTER http://www.postgresql.org/docs/9.1/static/sql-cluster.html和FILLFACTOR http://www.postgresql.org/docs/9.1/static/sql-createtable.htmlhttp://www.postgresql.org/docs/9.1/static/sql-createindex.html

请注意,FILLFACTOR可以同时应用于表和索引。


5

还有另一件事尚未进入方程式:HOT update。相关答案:

设置FILLFACTOR低至20 不会显得过大。它使桌子膨胀至最大尺寸的五倍。如果HOT更新有效,那么您通常不必走低

有例外:HOT更新只能重用先前事务中的无效元组,而不能重用相同并发的元组。因此,繁重的并发负载或重复更新同一行的长事务可以保证如此低(甚至更低)的设置。

如果您有较大的更新,一次要更改表的大部分,则可能需要将它们拆分为几个块,理想情况下,一次只能更改数据页面上适合本地的行数。但这很难估计和调节。

请注意,仅当更改的列以任何方式涉及索引(既不作为数据也不作为部分索引的条件)时,HOT更新才起作用。您可能使用已更新列上的索引来阻止HOT更新。如果这些都是消耗性的,那么没有它们,您可能会获得更好的整体性能。

最后,您可以为每个表设置autovacuum参数。您可以使用激进的设置来定位大量更新的表,从而使行的打包比仅行的更加紧密FILLFACTOR 20


1
有趣的东西,我将对其进行阅读,并尝试更好地了解HOT更新对我的系统意味着什么。
CadentOrange

4

如果您的问题是文件碎片,那么不是,不是。在Postgres中,每个表都在文件系统中获取其自己的文件,或者如果使用TOAST,则获取文件集。例如,这与Oracle(或显然是MS-SQL)不同,在Oracle中,您创建了预先设置大小的表空间文件以将表放入其中-尽管即使扩展了表空间文件或文件系统被破坏,也可能存在文件系统碎片的问题。首先非常分散。

关于第二个问题...我不知道如何清理文件系统碎片,因为MS-Windows是我遇到碎片问题的唯一操作系统,而且我绝对不会运行MS-Windows需要这些天。也许将数据库文件放在其自己的磁盘上可以在某种程度上缓解这种情况。


请记住,您有内部PostgreSQL数据库碎片,而有外部文件系统碎片。我相信可以使用VACUUM以及使用CLUSTERS和FILLFACTOR减轻内部压力。可以通过运行给定文件系统的碎片整理来处理文件系统。Linux / Unix文件系统有时可能会变得支离破碎,这取决于工作负载和文件系统的类型。
Kuberchaun 2012年

如今,文件系统碎片化并不是NTFS真正的大问题。
a_horse_with_no_name 2012年

1
我以为NTFS臭名昭著?我的工作站计算机变得非常整洁,唯一可以控制的就是Windows7每天运行的计划碎片整理。
Kuberchaun 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.