postgresql - 调试高 PostgreSQL 内存使用率(每个连接)
问题描述
有没有办法检查分配给每个连接的内存是如何实际使用的?
从 PostgreSQL 9.3 升级到 PG 12 后,每个 PostgreSQL 连接的内存使用量增加了一倍甚至三倍。所以我不得不从 32GB 机器:shared_buffers = 8GB 内存用于连接 = 8GB 内存用于磁盘缓冲区 = 16GB 到:64GB 机器:shared_buffers = 8GB 内存用于连接 = 40GB 内存用于磁盘缓冲区 = 16GB
而且还不够。单个连接达到使用 170MB 的私有 ram 并不少见(如https://www.depesz.com/2012/06/09/how-much-ram-is-postgresql-using/Private
中所述),不与其他进程共享。smaps
如此高的内存使用率可能是什么原因?据我所知,它是持久的——在连接关闭之前不会释放内存。当我使用由 Wildfly 管理的连接池时,它们会被重复使用,并且它们很少被关闭和重新创建。
这是我的数据源定义:
<datasource jta="true" jndi-name="java:/MainDS" pool-name="MainDCPool">
<connection-url>jdbc:postgresql://dbhost/</connection-url>
<driver-class>org.postgresql.Driver</driver-class>
<driver>postgres</driver>
<pool>
<min-pool-size>1</min-pool-size>
<max-pool-size>30</max-pool-size>
</pool>
<security>
<user-name>dbuser</user-name>
<password>password</password>
</security>
<validation>
<valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker"/>
<validate-on-match>true</validate-on-match>
<background-validation>false</background-validation>
</validation>
<statement>
<share-prepared-statements>false</share-prepared-statements>
</statement>
<timeout>
<idle-timeout-minutes>1</idle-timeout-minutes>
</timeout>
</datasource>
到目前为止,我称之为告诉设置'idle-timeout-minutes = 1'并且min-pool-size=1
没有太大影响。看起来 WildFly 从池中选择随机连接(当应用程序请求时),因此它们中的任何一个都不太可能长时间保持空闲,并且池大小永远不会低于约 20 个连接
解决方案
原来原因是直方图(pg_stats)。它存储在每个连接的内存中,并且在具有大量分区的数据库中会导致大量开销。包含大/长值的列具有重大影响。降低单表 4 列及其分区的 STATISTICS 属性可将内存使用量(每个连接)减少 35%。升级本身并没有错,但是——作为升级过程的一部分——整个数据库被分析,default_statistics_target
为所有表应用了新的价值。
检查直方图大小:查找给定表 PostgreSQL 的直方图大小
推荐阅读
- vue.js - Vuex 在组件中存储奇怪的行为
- python - 将独立块填充到全局数组中的“进程”或“线程”策略?
- asp.net-core - 复制到 PreBuild 事件的发布目录输出
- opencv - Xcode 10.0 OpenCV Cpp 项目不从 info.plist 读取 NSCameraDescription
- java - 接受用户输入以选择要编辑的变量
- google-sheets - Vlookup 找不到参考单元格
- sql-server - 将更改从 oracle 复制到 Sql Server
- gcc - 在静态库的 .text 部分执行运行时 md5sum 的最简单方法
- javascript - 有没有办法用子列表迭代无序列表 - 没有 jQuery?
- reactjs - 在 DraftJS 中执行异步装饰?