18.4. 资源消耗

18.4.1. 内存

shared_buffers (integer)

设置数据库服务器将使用的共享内存缓冲区量。默认通常是 128 兆字节(128MB),但是如果你的内核设置不支持(在initdb时决定),那么可以会更少。这个设置必须至少为 128 千字节(BLCKSZ的非默认值将改变最小值)。不过为了更好的性能,通常会使用明显高于最小值的设置。

如果有一个专用的 1GB 或更多内存的数据库服务器,一个合理的shared_buffers开始值是系统内存的 25%。即使很大的shared_buffers有效,也会造成一些工作负载, 但因为PostgreSQL同样依赖操作系统的高速缓冲区,将shared_buffers设置为超过 40% 的RAM不太可能比一个小点值工作得更好。为了能把对写大量新的或改变的数据的处理分布在一个较长的时间段内,shared_buffers更大的设置通常要求对checkpoint_segments也做相应增加。

如果系统内存小于 1GB,一个较小的 RAM 百分数是合适的,这样可以为操作系统留下足够的空间。 同时,在 Windows 上,shared_buffers设置得较大也不一定有效。你会发现保持相对低的设置并且更多使用操作系统高速缓存会得到更好的结果。Windows 上可用的shared_buffers值通常是从 64MB 到 512 MB。

temp_buffers (integer)

设置每个数据库会话使用的临时缓冲区的最大数目。这些都是会话的本地缓冲区,只用于访问临时表。默认是 8 兆字节(8MB)。这个设置可以在独立的会话内部被改变,但是只有在会话第一次使用临时表之前才能改变; 在会话中随后企图改变该值是无效的。

一个会话将按照temp_buffers给出的限制根据需要分配临时缓冲区。如果在一个并不需要大量临时缓冲区的会话里设置一个大的数值, 其开销只是一个缓冲区描述符,或者说temp_buffers每增加一则增加大概 64 字节。不过,如果一个缓冲区被实际使用,那么它就会额外消耗 8192 字节(或者BLCKSZ字节)。

max_prepared_transactions (integer)

设置可以同时处于"prepared"状态的事务的最大数目(见PREPARE TRANSACTION)。把这个参数设置 为零(这是默认设置)将禁用预备事务特性。这个参数只能在服务器启动时设置。

如果你不打算使用预备事务,可以把这个参数设置为零来防止意外创建预备事务。如果你正在使用预备事务,你将希望把max_prepared_transactions至少设置为max_connections一样大,因此每一个会话可以有一个预备事务待处理。

当运行一个后备服务器时,这个参数必须至少与主服务器上的一样大。否则,后备服务器上将不会执行查询。

work_mem (integer)

指定在写到临时磁盘文件之前被内部排序操作和哈希表使用的内存量。该值默认为一兆字节(1MB)。注意对于一个复杂查询, 可能会并行运行好几个排序或者哈希操作;每个操作都会被允许使用这个参数指定的内存量,然后才会开始写数据到临时文件。同样,几个正在运行的会话可能并发进行这样的操作。因此被使用的总内存可能是work_mem值的好几倍,在选择这个值时一定要记住这一点。ORDER BYDISTINCT和归并连接都要用到排序操作。哈希连接、基于哈希的聚集以及基于哈希的IN子查询处理中都要用到哈希表。

maintenance_work_mem (integer)

指定在维护性操作(例如VACUUMCREATE INDEXALTER TABLE ADD FOREIGN KEY)中使用的 最大的内存量。其默认值是 16 兆字节(16MB)。因为在一个数据库会话中,一个时刻只有一个这样的操作可以被执行,并且一个数据库安装通常不会有太多这样的操作并发执行, 把这个数值设置得比work_mem大很多是安全的。 更大的设置可以改进清理和恢复数据库转储的性能。

注意当自动清理运行时,可能会分配这个内存的autovacuum_max_workers倍,因此要小心不要把该默认值设置得太高。

max_stack_depth (integer)

指定服务器的执行堆栈的最大安全深度。这个参数的理想设置是由内核强制的实际栈尺寸限制(ulimit -s所设置的或者本地等价物),减去大约一兆字节的安全边缘。需要这个安全边缘是因为在服务器中并非所有例程都检查栈深度,只是在关键的可能递规的例程(例如表达式计算)中才进行检查。默认设置是两兆字节(2MB),这个值相对比较小并且不可能导致崩溃。但是,这个值可能太小了,以至于无法执行复杂的函数。只有超级用户可以修改这个设置。

max_stack_depth参数设置得高于实际的内核限制将意味着一个失控的递归函数可能会导致一个独立的后端进程崩溃。 在PostgreSQL能够检测内核限制的平台上, 服务器将不允许把这个参数设置为一个不安全的值。不过,并非所有平台都能提供该信息,所以我们还是建议你在选择值时要小心。

18.4.2. 磁盘

temp_file_limit (integer)

指定一个会话能用于临时文件(如排序和哈希临时文件,或者用于保持游标的存储文件)的最大磁盘空间量。一个试图超过这个限制的事务将被取消。这个值以千字节计,并且-1(默认值)意味着没有限制。只有超级用户能够修改这个设置。

这个设置约束着一个给定PostgreSQL会话在任何瞬间所使用的所有临时文件的总空间。应该注意的是,与在查询执行中在幕后使用的临时文件相反,显式临时表所用的磁盘空间被这个设置所限制。

18.4.3. 内核资源使用

max_files_per_process (integer)

设置每个服务器子进程允许同时打开的最大文件数目。默认是 1000 个文件。如果内核强制一个安全的针对每个进程的限制,那么你不用操心这个设置。但是在 一些平台上(特别是大多数 BSD 系统),如果很多进程都尝试打开很多文件,内核将允许独立进程打开比个系统真正可以支持的数目大得多得文件数。如果你发现自己看到了"Too many open files"这样的失败,可尝试减小这个设置。这个参数只能在服务器启动时设置。

shared_preload_libraries (string)

这个变量指定一个或者多个在服务器启动的时候预先装载的共享库。例如'$libdir/mylib'可能会导致mylib.so(或者某些平台上的mylib.sl)从安装的标准库目录被预装载。所有库的名字会被转换成小写,除非使用了双引号。如果载入多个库,那么用逗号将它们的名字隔开。这个参数只能在服务器启动时设置。

可以用这个方法预装载PostgreSQL的过程语言库,通常是使用'$libdir/plXXX'语法,其中的XXXpgsqlperltclpython

通过预装载一个共享库,可以避免第一次使用这个库时的加载时间。不过,启动每个新服务器进程的时间可能会 小幅增加,即使那个进程从来不会使用该库。因此我们只是建议只把那些将被大多数会话使用的库放在这个参数中。

Note: 在 Windows 主机上,服务器启动时预装载一个库不会减少开始每个新服务器进程所需的时间; 每个服务器进程会重新载入所有的预装载库。不过,shared_preload_libraries在 Windows 主机上 仍然是有用的,因为某些共享库需要执行一些只有在 postmaster 启动时才能发生的操作(例如,一个共享库可能需要保留轻量级锁或共享内存,而在 postmaster 启动后无法做到这一点)。

如果没有找到指定的库,那么服务器启动将失败。

每一个支持 PostgreSQL 的库都有一个"magic block",它被检查以保证兼容性。出于这个原因,非 PostgreSQL 库不能用 这种办法加载。

18.4.4. 基于代价的清理延迟

VACUUMANALYZE命令的执行过程中,系统维持着一个内部计数器来跟踪各种被执行的I/O操作的估算开销。当累计的代价达到一个限制(由vacuum_cost_limit指定),执行这些操作的进程将按照vacuum_cost_delay所指定的休眠一小段时间。然后它将重置计数器并继续执行。

这个特性的出发点是允许管理员降低这些命令对并发的数据库活动产生的I/O影响。在很多情况下,VACUUMANALYZE等维护命令能否快速完成并不重要,而非常重要的是这些命令不会对系统执行其他数据库操作的能力产生显著的影响。基于代价的清理延迟提供了一种方式让管理员能够保证这一点。

对于手动发出的VACUUM命令,该特性默认被禁用。要启用它,只要把vacuum_cost_delay变量设为一个非零值。

vacuum_cost_delay (integer)

进程超过代价限制后将休眠的时间长度,以毫秒计。其默认值为0,这将禁用基于代价的清理延迟特性。正值将启用基于代价的清理。注意在很多系统上,实际的休眠延迟单位是10毫秒,将vacuum_cost_delay设置成不为10的倍数的值和将它设置为比该值大的10的倍数的效果相同。

在使用基于代价的清理时,vacuum_cost_delay的合适值通常很小,也许是10或20毫秒。调整清理时资源消耗最好的方法是调整其他清理代价参数。

vacuum_cost_page_hit (integer)

清理一个在共享缓存中找到的缓冲区的估计代价。它表示锁住缓冲池、查找共享哈希表和扫描页内容的代价。默认值为1。

vacuum_cost_page_miss (integer)

清理一个必须从磁盘上读取的缓冲区的代价。它表示锁住缓冲池、查找共享哈希表、从磁盘读取需要的块以及扫描其内容的代价。默认值为10。

vacuum_cost_page_dirty (integer)

当清理修改一个之前干净的块时需要花费的估计代价。它表示再次把脏块刷出到磁盘所需要的额外I/O。默认值为20。

vacuum_cost_limit (integer)

将导致清理进程休眠的累计代价。默认值为200。

Note: 有些操作会保持关键性的锁,这样可以尽快完成。基于代价的清理延迟在这类操作期间不会发生。因此有可能代价会累计至大大超过指定的限制。为了防止在这种情况下的无意义的长时间延迟,实际延迟的计算方式是vacuum_cost_delay * accumulated_balance / vacuum_cost_limit,且最大值是vacuum_cost_delay * 4。

18.4.5. 后台写入器

有一个独立的服务器进程,叫做后台写入器,它的功能就是发出写"脏"(新的或修改过的)共享缓冲区的命令。它写出共享缓冲区,这样让处理用户查询的服务器进程很少或者永不等待写动作的发生。不过,后台写入器确实会增加 I/O 的总负荷,因为虽然在每个检查点间隔中一个重复弄脏的页面可能只会写出一次,但在同一个间隔中后台写入器可能会把它写出好几次。在这一小节讨论的参数可以被用于调节本地需求的行为。

bgwriter_delay (integer)

指定后台写入器活动轮次之间的延迟。在每个轮次中,写入器都会为一定数量的脏缓冲区发出写操作(可以用下面的参数控制)。然后它就休眠 bgwriter_delay毫秒, 然后重复动作。默认值是 200 毫秒(200ms)。注意在许多系统上,休眠延迟的有效解析度是 10 毫秒;因此,为bgwriter_delay设置一个 不是 10 的倍数的值与把它设置为下一个更高的 10 的倍数是一样的效果。这个选项只能在服务器命令行上或者在postgresql.conf文件中设置。

bgwriter_lru_maxpages (integer)

在每个轮次中,不超过这么多个缓冲区将被后台写入器写出。把这个参数设置为零可禁用后台写出(注意被一个独立、专用辅助进程管理的检查点不受影响)。默认值是 100 个缓冲区。这个参数只能在postgresql.conf文件中或在服务器命令行上设置。

bgwriter_lru_multiplier (floating point)

每一轮次要写的脏缓冲区的数目基于最近几个轮次中服务器进程需要的新缓冲区的数目。 最近所需的平均值乘以bgwriter_lru_multiplier可以估算下一轮次中将会需要的缓冲区数目。脏缓冲区将被写出直到有很多干净可重用的缓冲区(然而,每一轮次中写出的缓冲区数不超过bgwriter_lru_maxpages)。 因此,设置为 1.0 表示一种"刚刚好的"策略,这种策略会写出正好符合预测值的数目的缓冲区。 更大大的值可以为需求高峰提供某种缓冲,而更小的值则需要服务进程来处理一些写出操作。默认值是 2.0。这个参数只能在postgresql.conf文件中或在服务器命令行上设置。

较小的bgwriter_lru_maxpagesbgwriter_lru_multiplier可以降低由后台写入器造成的额外 I/O 开销。但更可能的是,服务器进程将必须自己发出写入操作,这会延迟交互式查询。

18.4.6. 异步行为

effective_io_concurrency (integer)

设置PostgreSQL可以同时被执行的并发磁盘 I/O 操作的数量。调高这个值,可以增加任何单个PostgreSQL会话试图并行发起的 I/O 操作的数目。 允许的范围是 1 到 1000,或 0 表示禁用异步 I/O 请求。当前这个设置仅影响位图堆扫描。

这个设置的一个很好的出发点是组成一个被用于该数据库的 RAID 0 条带或 RAID 1 镜像的独立驱动器数量(对 RAID 5 而言,校验驱动器不计入)。但是, 如果数据库经常忙于在并发会话中发出的多个查询,较低的值可能足以使磁盘阵列繁忙。比保持磁盘繁忙所需的值更高的值只会造成额外的 CPU 开销。

对更特殊的系统(如,基于内存的存储或受限于总线带宽的RAID阵列)来说,正确的值可能是可用的 I/O 路径数。需要一些实验来找出最佳值。

异步 I/O 依赖于一个有效的posix_fadvise函数(一些操作系统可能没有)。 如果不存在这个函数,将这个参数设置为除 0 之外的任何东西将导致错误。在一些操作系统上(如Solaris)虽然提供了这个函数,但它不会做任何事情。