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