PostgreSQL中与内存有关的配置参数如下。
shared_buffers:共享缓存区的大小,相当于Oracle数据库中的SGA,主要做数据块的缓存。
work_mem:为每个进程单独分配的内存,主要用于排序、HASH等操作。
maintence_work_mem:为每个进程单独分配的内存,主要是进行维护操作时需要的内存,如VACUUM、CREATE INDEX、ALTER TABLE ADD FOREIGN KEY等操作需要的内存。
autovacuum_work_mem:从PostgreSQL 9.4版本开始新增的参数。在PostgreSQL 9.4之前的版本中,AutoVacuum的每一个worker进程与手动做VACUUM一样,分配的内存大小都是由maintence_work_mem参数控制的,现在分开了,AutoVacuum的worker进程由该参数控制,手动VACUUM时分配的内存大小仍由maintence_work_mem参数控制。此参数默认设置为“-1”,即与原先的行为是一样的,当把此参数设置为其他值时,可以为AutoVacuum的每个worker进程做VACUUM操作时指定不同的内存值。
temp_buffers:指定临时表的缓存的大小,这是为每个不同的进程单独分配的内存,不在共享内存中。默认为8MB,通常保持默认值就可以了。
wal_buffers:指定WAL日志缓存的大小,默认值是“-1”,即会根据shared_buffer的大小自动设置。选择等于shared_buffers的1/32的尺寸(大约3%),但是不小于64KB也不大于WAL文件的尺寸(通常为16MB)。不应该超过WAL文件的大小,通常保持默认值就可以了,如果手动设置,一般为4MB~16MB。
huge_pages:是否使用大页,默认设置是“try”,表示尽量使用大页,如果操作系统未开启大页或分配的大页内存太小,数据库虽仍然能启动,但不再使用大页内存。
effective_cache_size:该参数实际上与具体的内存分配没有关系,它是告诉优化器在估计SQL的执行代价时假设有多少磁盘缓存,注意主要指文件系统缓存,通常设置为机器总内存的80%,设置得多一些(如90%)或少一些(如50%)并不会有严重的影响。shared_buffers,即共享缓存区的大小,因为要多个进程中共享,所以必须使用共享内存技术来存放。PostgreSQL的数据文件都在文件系统中,操作系统的文件系统也有缓存,这有可能会导致数据库的数据块除了在PostgreSQL的共享内存中有一个副本以外,在文件系统的缓存中也有一个副本,因此造成内存利用率不高,这就是PostgreSQL中的DoubleBuffering问题。在Oracle数据库中,通过设置Direct I/O来避免双缓存问题,但PostgreSQL中未实现对Direct I/O的支持。为了减少双缓存问题带来的影响,通常使用以下方法解决:
设置较小的shared buffer,将大多数内存给文件系统缓存使用,如在一台有24GB内存的机器上,可以把PostgreSQL中的shared buffer设置为较小值,如500MB~1GB,其他内存都留给文件系统缓存使用。
设置信号
kernel.sem=5010 3256500 5010 650
对一些连接数很大且内存较大的PostgreSQL数据库,强烈建议配置大页。这不仅是因为大页的性能会高一些,也是为了避免页表过大。操作系统把逻辑地址映射成物理地址时,需要把映射关系也存储到一个内存中,这部分内存就是页表。在Linux操作系统中,即使是同一块共享内存,每个进程中的逻辑地址也是不相同的,因此不同进程中的映射表项也不相同。在64位的机器上,每个4k页需要占用大约8字节的内存,一台48GB内存的机器,如果分配了24GB共享内存,则每个进程的页表大小为(24G/4k)×8=48MB,如果服务器连接上500个进程,页表的大小将是500×48=24GB。这会立刻把机器上所有内存吃光,因而会产生很大的问题。当然并不是每个新连接一连接上来,后面进程的页表就会马上分配48MB,当进程需要建立逻辑地址与物理地址之间的关系时才会分配,所以进程占用的页表空间是缓慢增加的,但最终还是可能会占用很大的页表内存。
要查看是否存在这个问题,可以使用如下命令来检查页表的大小:
cat /proc/meminfo |grep PageTables
如果发现页表的大小不是几十兆,而是达到了1GB以上,就说明数据库存在此问题。
PostgreSQL 9.4版本开始支持大页,打开大页的方法是设置参数“huge_pages”,命令如下:
huge_pages = try
操作系统中大页的设置项在/etc/sysctl.conf中,命令如下:
vm.nr_hugepages=10240
上例表示设置了大小为10240*2MB的内存,即大约为20GB内存。使用如下命令让该设置生效:
sysctl -p
cat /proc/sys/vm/nr_hugepages
最后还有一个需要注意的问题,即Linux中还有一个透明大页(Transparent Hugepage),即Linux自动进行大小页的转换和自动管理,但目前在Redhat 7.X/CentOS 7.X下该功能会带来性能的抖动或下降,通常建议关闭透明大页,关闭方法如下:
grubby --update-kernel=ALL --args="transparent_hugepage=never
访问在共享内存中的数据块数×vacuum_cost_page_hit+访问在磁盘上的数据块数×vacuum_cost_page_miss+修改干净的在磁盘中的数据块数×vacuum_cost_page_dirty这些参数的意义如下:
要想减少执行VACUUM命令对现有系统的影响,可以把vacuum_cost_delay设置为一个合适的值,命令如下:
osdba=# set vacuum_cost_delay to 1;
SET
osdba=# vacuum;
VACUUM
但有时把vacuum_cost_delay设置为最小值1时,VACCUM操作的执行效率还是太低,这是因为默认的vacuum_cost_limit值太小,vacuum_cost_limit默认是“200”,如果是SSD硬盘可以把该值设置为“10000”,如果是一般带缓存的硬件Raid卡输出的机械硬盘,设置为1000~2000比较合适。
对于自动VACUUM即AutoVacuum,也有一组与上面类似的参数来实现相同的功能。
通常一张表变更的行数超过一定的阈值时,AutoVacuum才会对这张表做VACUUM,该阈值的计算公式如下:
autovacuum_vacuum_scale_factor×表上记录数+autovacuum_vacuum_threshold
公式中的各参数说明如下。
autovacuum_vacuum_threshold:当表上发生变化的行数至少达到此参数值时,才可能让AutoVacuum对其进行VACUUM,(这里说“可能”是因为还有另一个参数“autovacuum_vacuum_scale_factor”同时控制VACUUM的执行条件),默认值为“50”。也可以在表上单独设置此参数,让不同的表有不同的配置。
autovacuum_vacuum_scale_factor:触发VACUUM的第二个阈值条件。调整这两个参数的值可以改变AutoVacuum的工作量,从而提升性能。对于一些大表,autovacuum_vacuum_scale_factor设置为“50”有一些小了,可以在大表上单独设置一个较大的值,如“90”,命令如下
alter table big_table set (autovacuum_vacuum_threshold=90,toast.autovacuum_vacuum_threshold=90);
禁止SELinux
SELinux的限制很多,为了操作方便,我们会关闭SELinux,关闭的方法是修改/etc/selinux/config:
SELINUX=disabled
getenforce
关闭防火墙
systemctl stop iptables
systemctl disable iptables
systemctl stop firewalld
systemctl disable firewalld
ulimit的配置
* soft nofile 65536
* hard nofile 65536
* soft nproc 131072
* hard nproc 131072
* soft memlock -1
* hard memlock -1
XFS文件系统的配置
/dev/sde /data xfs nodev,discard,noatime,inode64,allocsize=16m 0
设备的I/O调度策略设置
grubby --update-kernel=ALL --args="elevator=deadline"
设置内存大页
grubby --update-kernel=ALL --args="transparent_hugepage=never"
设置页面大小为1GB的大页共32GB,命令如下
grubby --update-kernel=ALL --args="default_hugepagesz=1G hugepagesz=1G hugepages=32"
sysctl.conf的配置
vm.swappiness=0
vm.overcommit_memory=2
vm.overcommit_ratio=85
vm.dirty_background_ratio=1
vm.dirty_ratio=2
kernel.shmmax = 274877906944
kernel.shmall = 67108864
kernel.sem=20 13000 20 650
kernel.sysrq = 1
kernel.core_uses_pid = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.msgmni = 2048
net.ipv4.tcp_syncookies = 1
net.ipv4.ip_forward = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.conf.all.arp_filter = 1
net.ipv4.ip_local_port_range = 1025 65535
net.core.netdev_max_backlog = 10000
net.core.rmem_max = 2097152
net.core.wmem_max = 2097152
net.core.somaxconn = 2048
上面的一些重要配置项的说明如下。
listen_addresses = '*' # what IP address(es) to listen on;
port = 5432 # (change requires restart)
max_connections = 3000 # (change requires restart)
superuser_reserved_connections = 10 # (change requires restart)
tcp_keepalives_idle = 5 # TCP_KEEPIDLE, in seconds;
tcp_keepalives_interval = 5 # TCP_KEEPINTVL, in seconds;
tcp_keepalives_count = 3 # TCP_KEEPCNT;
shared_buffers = 32GB
huge_pages = on
# you actively intend to use prepared transactions.
work_mem = 4MB
maintenance_work_mem = 128MB
autovacuum_work_mem = 256MB
wal_writer_delay = 10ms
max_wal_size = 50GB
min_wal_size = 40GB
checkpoint_timeout = 15min
max_locks_per_transaction =256
checkpoint_completion_target = 0.9 # checkpoint target duration, 0.0 - 1.0
effective_cache_size = 256GB
log_destination = 'csvlog' # Valid values are combinations of
logging_collector = on # Enable capturing of stderr and csvlog
log_directory = 'pg_log' # directory where log files are written,
log_truncate_on_rotation = on # If on, an existing log file with the
log_rotation_age=3d
log_rotation_size=100MB
autovacuum = on # Enable autovacuum subprocess? 'on'
log_autovacuum_min_duration = 0
autovacuum_max_workers = 10 # max number of autovacuum subprocesses
autovacuum_naptime = 1min # time between autovacuum runs
autovacuum_vacuum_threshold = 500 # min number of row updates before vacuum
autovacuum_analyze_threshold = 500 # min number of row updates before analyze
autovacuum_vacuum_scale_factor = 0.2 # fraction of table size before vacuum
autovacuum_analyze_scale_factor = 0.1 # fraction of table size before analyze
autovacuum_vacuum_cost_delay = 2ms # autovacuum_vacuum_cost_delay
autovacuum_vacuum_cost_limit = 5000 # default vacuum cost limit
wal_compression = on
lock_timeout=600000
statement_timeout=3600000
log_min_error_statement=error
log_min_duration_statement=5s
temp_file_limit=20G #控制临时表空间size
vacuum_cost_limit = 5000 #sas 盘2000,SSD为10000
vacuum_cost_delay = 2ms
checkpoint_completion_target=0.9
random_page_cost = 1.1
log_checkpoints =on
log_statement = 'ddl'
idle_in_transaction_session_timeout = 600000 # 自动清理 idle session
track_io_timing = on
track_functions = all
shared_preload_libraries = 'pg_stat_statements'
track_activity_query_size = 2048
pg_stat_statements.max = 10000
pg_stat_statements.track = all
pg_stat_statements.track_utility = off
pg_stat_statements.save = on
archive_mode = 'on'
archive_command = '/usr/bin/true'
一些重要配置项的说明如下。