衡阳企业网站排名优化,深圳网站建设 联雅网络,澧县网站建设,怎样加强组织建设在了解如在PG中如何配置大页之前#xff0c;我们先要对大页进行一定的了解#xff0c;为什么要配置大页#xff0c;配置大页的好处有哪些。
我们日常的操作系统中#xff0c;程序不直接使用内存#xff0c;而是使用虚拟内存地址来处理内存分配#xff0c;避免计算的复杂…在了解如在PG中如何配置大页之前我们先要对大页进行一定的了解为什么要配置大页配置大页的好处有哪些。
我们日常的操作系统中程序不直接使用内存而是使用虚拟内存地址来处理内存分配避免计算的复杂性和物理地址映射到应用程序内存空间的复杂性。虚拟地址模型在应用程序读取或写入内存时立即将虚拟地址转换为相应的物理内存地址。这种映射结构存储在page tables中这是一种分层组织的查找表。
如下图在运行中的程序使用虚拟内存映射到物理内存 下图为虚拟内存通过page table映射到物理内存 地址转换依靠MMU实现MMU是内存管理单元是硬件设备在CPU内部 如下图使用MMU使用TLB的加速映射 下图说明了TLB的加速原理如果物理地址在TLB中命中直接转换为物理地址只访问一次内存地址否则扫描page table查找地址然后映射条目到TLB然后再转换为物理地址这样就有两次内存访问。最差的是page table也没有需要从磁盘写到page table那么这样效率会更慢。 因为TLB只能保存几千个条目那么我们为了提高性能可以有两个办法
增加TLB的大小升本太高受限硬件提升有限增加内存page的大小如果TLB只能对应512个页表项那么能否每个page对应1G的内存呢这样程序访问512G的内存也能保证都利用到TLB缓存了。
如下图4K2MB1GB在256GB内存下对应的页面数两 操作系统上的内存分配都是通过分配单个或多个可用内存页来完成的。这些页面都是特定大小主要取决于操作系统。在Linux上内存分配使用的默认页面大小是4kB。 因此我们可以想象分配大量内存需要在页表中保存大量页面以便将它们映射到相应的物理地址。查找虚拟地址需要多次内存访问与CPU速度相比这是非常昂贵的。因此现在的cpu维护一个叫Translation Lookaside Buffer (TLB)的缓存TLB是一个加速虚拟内存和物理内存之间转换的缓存。
TLB的大小被限制在几千个条目特别是在具有高内存特定内存工作负载的系统上很快就会成为瓶颈。例如像PostgreSQL这样的数据库使用共享缓存池来实现进程间通信(IPC)、块层访问和其他功能这很快就会给TLB带来很大的压力因为虚拟地址映射的数量是有限的。特别是共享缓冲池配置大内存(比如100GB的shared buffer)的时候这些实例可能因此受到性能影响。
所以我们在内存很大的时候比如有256G内存可以设置huge page提高效率。在x86系统上我们通常可以设置2MB或1GB大小IBM POWER允许64kB、16MB和16GB。 在x86架构中配置大页时默认的页面大小是2MB。可以通过/proc/meminfo获取你的系统当前设置:
cat /proc/meminfo | grep -i HugePage
AnonHugePages: 161792 kB
ShmemHugePages: 0 kB
FileHugePages: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kBHugePages_Total为零表示目前没有配置大页面因此HugePages_Rsvd,HugePages_Free和HugePages_Surp也都为零。Hugepagesize显示了内核中当前为大页面配置的默认大小。在稍后配置大页时我们将会考虑如何设置这些值。
如下图可以通过查看/proc/cpuinfo中的flages,是否支持各种大页的尺寸 PG中大页的使用
PostgreSQL中只有shared buffer中可以使用大页来分配内存。而work_mem, maintenance_work_mem, autovacuum_work_mem这些动态内存的分配不会使用大页。此外用于在并行查询工作之间传输数据和通信的动态共享内存段不会自动请求它们但有一个例外我将在下一段关于在Linux上为大型页面配置PostgreSQL的内容中描述。还需要在所谓的mmap段中分配共享缓冲区这是由shared_memory_type参数控制的。这是Linux上的默认设置。系统V共享内存只被PostgreSQL用来初始化一个非常小的共享内存区域;缓冲池本身是通过mmap分配的。
对于Linux上的PostgreSQL不推通过THP配置大页因为它不会直接分配大页而是在需要时提供给它们。THP是可切换的与显式配置的大页相比它被认为是一个较慢的选择。在这种情况下FreeBSD等其他操作系统提供了更好的支持。
在PG15中数据库关闭状态可以通过命令直接计算需要大页大小如下 su - postgres/usr/pgsql-15/bin/postgres --shared-buffers20GB -D $PGDATA -C shared_memory_size_in_huge_pages
10475PG中通过huge_pages参数配置是否开启大页 try:尝试分配大页如果不能则退回到正常的页面分配(目前的默认设置) onshared buffer强制使用大页 off不使用大页
上面计算出需要设置的大页数后可以通过修改文件来修改大页数量,注意只是临时修改吗重启无效 echo 10475 /proc/sys/vm/nr_hugepages再次查看大页设置
grep -i hugepage /proc/meminfo
AnonHugePages: 124928 kB
ShmemHugePages: 0 kB
FileHugePages: 0 kB
HugePages_Total: 10475
HugePages_Free: 10475
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB永久修改配置
cat /etc/sysctl.d/01-nr-hugepages.conf
vm.nr_hugepages10475修改 postgresql.conf文件中以下参数
shared_buffers 20GB
huges_pages on
huge_page_size 0 #use default kernel settingPostgreSQL必须启动(或重新启动)并且应该通过默认的大页大小分配其共享缓冲池。查看/proc/meminfo信息。输出如下:
grep -i hugepage /proc/meminfo
AnonHugePages: 176128 kB
ShmemHugePages: 0 kB
FileHugePages: 0 kB
HugePages_Total: 10475
HugePages_Free: 10264
HugePages_Rsvd: 10264
HugePages_Surp: 0
Hugepagesize: 2048 kB使用pmap工具可以查看postmaster进程分配的内存段
pmap $(head -n1 /var/lib/pgsql/15/data/postmaster.pid) | grep huge
00007f11a5400000 21452800K rw-s- anon_hugepage (deleted)在PostgreSQL如何使用大页面的一节中我们应该解释一下那里提到的异常。通常动态共享内存分配是有目的的例如并行查询工作者处理并行查询时。默认情况下这些动态分配的内存不是由mmap完成的而是PostgreSQL在Linux上默认通过shm_open()使用posix API。在这种情况下不分配大页。但是在并行查询时也会产生内存压力特别是在需要处理大量数据时。
从版本14开始PostgreSQL提供了参数min_dynamic_shared_memory。配置后指定的值定义了在服务器启动时创建的共享内存中的额外空间这些空间应该用于并行查询工作。由于它是与缓冲池一起分配的因此它也使用了大页进行分配。我们可以扩展上面的例子并重新计算设置2GB的额外共享内存用于并行查询:
/usr/pgsql-15/bin/postgres -D $PGDATA --min-dynamic-shared-memory2GB --shared-buffers20GB -C shared_memory_size_in_huge_pages
11499同样需要停止PostgreSQL实例才能成功执行该命令。与前一个示例相比现在要保留的大页面的数量增加了2GB。
如果PG版本低于15怎么办
这些版本更难处理。特别是需要保留多少大页的计算比较麻烦。到目前为止最好的解决方案就是手动启动PostgreSQL设置huge_pageson然后调试参数。在这种情况下如果不能分配请求的共享内存大小PostgreSQL打印以下错误消息:
FATAL: could not map anonymous shared memory: Cannot allocate memory
HINT: This error usually means that PostgreSQLs request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently 21965570048 bytes), reduce PostgreSQLs shared memory usage, perhaps by reducing shared_buffers or max_connections.
LOG: database system is shut down注意HINT部分它告诉我们PostgreSQL想要分配21965570048字节的共享内存。这个值可以用来计算页面的数量。这个数字的问题是当我们将共享缓冲区指定为20GB时这比我们所要求的大一些。这是因为PostgreSQL还需要为其他内部进程(如wal_buffers或max_locks_per_transactions)提供额外的共享内存。扩展可能需要额外的共享 内存。PostgreSQL内部使用了一个近似如下的公式
((shm size (BLKSZ - (shm size % BLKSZ))) / (huge page size * 1024)) 1 num huge pages
#假设我们的数据库的BLKSZ是以8KB的page编译安装的
((21965570048 (8192 - (21965570048 % 8192))) / (2048 * 1024)) 1 10475track_activity_query_size设置
另外要注意track_activity_query_size的设置默认1024如果超过那么pg_stat_activitypg_stat_statements中记录sql的长度会被截断。但是一定要注意如果加大该设置会分配max_connections * track_activity_query_size的内存来保存我们的语句。 如上所述PostgreSQL使用共享内存来存储这些统计信息。PostgreSQL不能动态更改内存段的大小。因此更改track_activity_query_size也需要重新启动PostgreSQL。所以在启用实例前一定要考虑好如何设置该参数。另外还要注意该参数设置大了那么pg_stat_statements也会变大可能也会影响系统性能一定要注意定期使用该函数重置pg_stat_statements_reset
参考 https://courses.teresco.org/cs432_f02/lectures/12-memory/12-memory.html https://www.cybertec-postgresql.com/en/huge-pages-postgresql/ https://www.cybertec-postgresql.com/en/fixing-track_activity_query_size-in-postgresql-conf/