首先,始终使用最新版本的 PostgreSQL。性能改进总是会到来,所以如果你正在调整旧版本,你可能会浪费你的时间。例如,PostgreSQL 9.2 significantly improves the speed of TRUNCATE 当然添加了仅索引扫描。即使是次要版本也应始终遵循;见version policy。
注意事项
Do NOT put a tablespace on a RAMdisk or other non-durable storage.
如果您丢失了一个表空间,整个数据库可能会被损坏并且如果不做大量工作就很难使用。与仅使用 UNLOGGED 表并拥有大量 RAM 用于缓存相比,这几乎没有什么优势。
如果你真的想要一个基于 ramdisk 的系统,initdb 在 ramdisk 上创建一个全新的集群,initdb在 ramdisk 上创建一个新的 PostgreSQL 实例,这样你就有了一个完全一次性的 PostgreSQL 实例。
PostgreSQL 服务器配置
测试时,您可以将服务器配置为non-durable but faster operation。
这是 PostgreSQL 中 fsync=off 设置唯一可接受的用途之一。这个设置几乎告诉 PostgreSQL 不要打扰有序写入或任何其他讨厌的数据完整性保护和崩溃安全的东西,如果你断电或操作系统崩溃,它可以完全丢弃你的数据。
不用说,你永远不应该在生产环境中启用fsync=off,除非你使用 Pg 作为临时数据库来存储你可以从其他地方重新生成的数据。当且仅当您关闭 fsync 时也可以关闭 full_page_writes,因为它不再有任何好处。请注意,fsync=off 和 full_page_writes 适用于 集群 级别,因此它们会影响 PostgreSQL 实例中的所有数据库。
对于生产用途,您可以使用synchronous_commit=off 并设置commit_delay,因为您将获得与fsync=off 相同的许多好处,而没有巨大的数据损坏风险。如果启用异步提交,您确实会丢失最近的数据 - 仅此而已。
如果您可以选择稍微修改 DDL,您还可以使用 Pg 9.1+ 中的 UNLOGGED 表来完全避免 WAL 日志记录,并以在服务器崩溃时表被擦除为代价来获得真正的速度提升。没有使所有表不记录的配置选项,它必须在CREATE TABLE 期间设置。除了有利于测试之外,如果您的数据库中有充满生成或不重要数据的表,而这些数据包含您需要安全的内容,这将非常方便。
检查您的日志,看看您是否收到有关检查点过多的警告。如果你是,你应该增加你的checkpoint_segments。您可能还需要调整 checkpoint_completion_target 以平滑写入。
调整 shared_buffers 以适应您的工作量。这取决于操作系统,取决于您的机器的其他情况,并且需要一些试验和错误。默认值非常保守。如果在 PostgreSQL 9.2 及更低版本上增加shared_buffers,您可能需要增加操作系统的最大共享内存限制; 9.3 及更高版本更改了他们使用共享内存的方式来避免这种情况。
如果您只使用几个连接来完成大量工作,请增加 work_mem 以给它们更多的 RAM 来进行排序等操作。请注意,work_mem 设置太高会导致用尽-内存问题,因为它是按排序而不是按连接,因此一个查询可以有许多嵌套排序。如果您在EXPLAIN 中看到排序溢出到磁盘或使用log_temp_files setting 记录(推荐),那么您只有真的需要增加work_mem,但更高的值也可能让Pg 选择更智能的计划.
正如另一位发帖人所说,如果可能,将 xlog 和主表/索引放在单独的 HDD 上是明智的。单独的分区是毫无意义的,你真的想要单独的驱动器。如果您使用fsync=off 运行,这种分离的好处要少得多,而如果您使用UNLOGGED 表,则几乎没有。
最后,调整您的查询。确保您的random_page_cost 和seq_page_cost 反映了您系统的性能,确保您的effective_cache_size 是正确的,等等。使用EXPLAIN (BUFFERS, ANALYZE) 检查单个查询计划,并打开auto_explain 模块以报告所有慢查询。您通常可以通过创建适当的索引或调整成本参数来显着提高查询性能。
AFAIK 无法将整个数据库或集群设置为 UNLOGGED。能够这样做会很有趣。考虑在 PostgreSQL 邮件列表中询问。
主机操作系统调优
您也可以在操作系统级别进行一些调整。您可能想要做的主要事情是说服操作系统不要积极地将写入刷新到磁盘,因为您真的不在乎它们何时/是否写入磁盘。
在 Linux 中,您可以使用virtual memory subsystem 的dirty_* 设置来控制它,例如dirty_writeback_centisecs。
将写回设置调整为过于宽松的唯一问题是,某些其他程序的刷新可能会导致所有 PostgreSQL 的累积缓冲区也被刷新,从而在所有内容都阻塞写入时导致大停顿。您可以通过在不同的文件系统上运行 PostgreSQL 来缓解这种情况,但某些刷新可能是设备级别或整个主机级别而不是文件系统级别,因此您不能依赖它。
此调整确实需要调整设置以查看最适合您的工作负载的设置。
在较新的内核上,您可能希望确保将 vm.zone_reclaim_mode 设置为零,因为与 PostgreSQL 管理 shared_buffers 的方式发生交互,这可能会导致 NUMA 系统(目前大多数系统)出现严重的性能问题。
查询和工作负载调整
这些确实需要更改代码;他们可能不适合你。有些是您可以申请的。
如果您不将工作批量处理成更大的事务,请开始。很多小交易都是昂贵的,所以你应该尽可能地批量处理东西。如果您使用的是异步提交,这不太重要,但仍然强烈推荐。
尽可能使用临时表。它们不会产生 WAL 流量,因此它们的插入和更新速度要快得多。有时值得将一堆数据放入临时表中,根据需要对其进行操作,然后执行INSERT INTO ... SELECT ... 将其复制到最终表中。请注意,临时表是每个会话的;如果您的会话结束或您失去连接,那么临时表就会消失,并且没有其他连接可以看到会话临时表的内容。
如果您使用的是 PostgreSQL 9.1 或更新版本,您可以使用 UNLOGGED 表来存储您可以承受丢失的数据,例如会话状态。这些在不同的会话中是可见的,并在连接之间保留。如果服务器不干净地关闭,它们会被截断,因此它们不能用于您无法重新创建的任何东西,但它们非常适合缓存、物化视图、状态表等。
一般来说,不要DELETE FROM blah;。请改用TRUNCATE TABLE blah;;当您将所有行转储到表中时,它会快得多。如果可以的话,在一个TRUNCATE 调用中截断许多表。但是,如果您一遍又一遍地做很多TRUNCATES 的小桌子,那就需要注意了;见:Postgresql Truncation speed
如果您没有外键索引,DELETEs 涉及由这些外键引用的主键将会非常缓慢。如果您希望从引用的表中创建DELETE,请确保创建此类索引。 TRUNCATE 不需要索引。
不要创建你不需要的索引。每个索引都有维护成本。尝试使用最小的索引集并让位图索引扫描将它们组合起来,而不是维护太多庞大、昂贵的多列索引。如果需要索引,请尝试先填充表,然后在最后创建索引。
硬件
如果您可以管理它,拥有足够的 RAM 来容纳整个数据库是一个巨大的胜利。
如果您没有足够的 RAM,存储速度越快越好。即使是便宜的 SSD 也会对旋转生锈产生巨大影响。不过,不要相信廉价的 SSD 用于生产,它们通常不具备碰撞安全性,并且可能会吃掉您的数据。
学习
Greg Smith 的书 PostgreSQL 9.0 High Performance 尽管提到了一个较旧的版本,但仍然具有相关性。它应该是一个有用的参考。
加入 PostgreSQL 通用邮件列表并关注它。
阅读: