首页 > 解决方案 > 调试高 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 个连接

标签: postgresqljdbcwildflypostgresql-12

解决方案


原来原因是直方图(pg_stats)。它存储在每个连接的内存中,并且在具有大量分区的数据库中会导致大量开销。包含大/长值的列具有重大影响。降低单表 4 列及其分区的 STATISTICS 属性可将内存使用量(每个连接)减少 35%。升级本身并没有错,但是——作为升级过程的一部分——整个数据库被分析,default_statistics_target为所有表应用了新的价值。

检查直方图大小:查找给定表 PostgreSQL 的直方图大小


推荐阅读