首先,请始终使用最新版本的PostgreSQL。性能改进总是会不断出现,因此如果您要调整旧版本,可能会浪费时间。例如,PostgreSQL 9.2大大提高了速度TRUNCATE
,当然也增加了仅索引扫描。即使是较小的发布,也应始终遵循;请参阅版本政策。
不要
千万不要把表放在ramdisk上或其他非耐久存。
如果丢失表空间,则整个数据库可能会损坏,并且如果不进行大量工作就很难使用。与仅使用UNLOGGED
表和拥有大量RAM用于高速缓存相比,这几乎没有什么好处。
如果您确实想要一个基于ramdisk的系统,initdb
则通过在ramdisk上initdb
使用新的PostgreSQL实例,在ramdisk 上建立一个全新的集群,因此您将拥有一个完全可抛弃的PostgreSQL实例。
PostgreSQL服务器配置
测试时,您可以将服务器配置为非耐用但运行速度更快。
这是fsync=off
PostgreSQL中该设置的唯一可接受的用法之一。这个设置几乎告诉PostgreSQL不要打扰有序的写操作或任何其他讨厌的数据完整性保护和崩溃安全性的东西,如果断电或发生操作系统崩溃,它可以完全破坏数据。
不用说,fsync=off
除非将Pg用作可从其他地方重新生成的数据的临时数据库,否则切勿在生产中启用它。当且仅当您要关闭fsync full_page_writes
时,它也可以关闭,因为它不再起作用。请注意fsync=off
并full_page_writes
在集群级别应用,因此它们会影响PostgreSQL实例中的所有数据库。
对于生产用途,您可以使用synchronous_commit=off
和设置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和主表/索引放置在单独的硬盘上是明智的。单独的分区是毫无意义的,您确实需要单独的驱动器。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高性能》一书虽然仍然有些旧,但仍然有意义。它应该是一个有用的参考。
加入PostgreSQL常规邮件列表并遵循它。
读: