如何检查我的数据库是否需要更多 RAM?

SDR*_*yes 12 postgresql performance memory database

您将如何检查您的 postgresql 数据库实例是否需要更多 RAM 内存来处理其当前工作数据?

小智 15

如果你都在 Linux 上,你的总物理 RAM 应该大于磁盘上的数据库大小,以最大限度地减少 I/O。最终,整个数据库都将位于操作系统读取缓存中,并且 I/O 将仅限于将更改提交到磁盘。我更喜欢通过运行“du -shc $PGDATA/base”来查找数据库大小——该方法将所有数据库聚合为一个数字。只要你比那个大,应该没问题。

此外,您可以查看堆和索引块提取的缓存命中率。这些测量了 PostgreSQL 共享缓冲区的命中率。这些数字可能有点误导——即使它可能是共享缓冲区缓存中的未命中,它仍然可能是操作系统读取缓存中的命中。尽管如此,共享缓冲区中的命中仍然比操作系统读取缓存中的命中便宜(反过来,这比必须返回磁盘便宜几个数量级)。

为了查看共享缓冲区命中率,我使用以下查询:

SELECT relname, heap_blks_read, heap_blks_hit,
    round(heap_blks_hit::numeric/(heap_blks_hit + heap_blks_read),3)
FROM pg_statio_user_tables
WHERE heap_blks_read > 0
ORDER BY 4
LIMIT 25;
Run Code Online (Sandbox Code Playgroud)

这为您提供了前 25 个最糟糕的违规者,其中所有表的缓冲区缓存都丢失了,其中必须从“磁盘”中获取至少一个块(同样,这可能是操作系统读取缓存或实际磁盘 I/O)。您可以增加 WHERE 子句中的值或为 heap_blks_hit 添加另一个条件以过滤掉很少使用的表。

通过将字符串“heap”全局替换为“idx”,可以使用相同的基本查询来检查每个表的总索引命中率。查看 pg_statio_user_indexes 以获得每个索引的细分。

关于共享缓冲区的快速说明:在 Linux 中,一个很好的经验法则是将配置参数shared_buffers设置为 RAM 的 1/4,但不超过 8GB。这不是硬性规定,而是调整服务器的一个很好的起点。如果您的数据库只有 4GB 而您有一个 32GB 的服务器,那么 8GB 的​​共享缓冲区实际上是多余的,您应该能够将其设置为 5 或 6 GB,并且仍有未来增长的空间。


小智 9

我做了这个 SQL 来显示表与磁盘命中率:

-- perform a "select pg_stat_reset();" when you want to reset counter statistics
with 
all_tables as
(
SELECT  *
FROM    (
    SELECT  'all'::text as table_name, 
        sum( (coalesce(heap_blks_read,0) + coalesce(idx_blks_read,0) + coalesce(toast_blks_read,0) + coalesce(tidx_blks_read,0)) ) as from_disk, 
        sum( (coalesce(heap_blks_hit,0)  + coalesce(idx_blks_hit,0)  + coalesce(toast_blks_hit,0)  + coalesce(tidx_blks_hit,0))  ) as from_cache    
    FROM    pg_statio_all_tables  --> change to pg_statio_USER_tables if you want to check only user tables (excluding postgres's own tables)
    ) a
WHERE   (from_disk + from_cache) > 0 -- discard tables without hits
),
tables as 
(
SELECT  *
FROM    (
    SELECT  relname as table_name, 
        ( (coalesce(heap_blks_read,0) + coalesce(idx_blks_read,0) + coalesce(toast_blks_read,0) + coalesce(tidx_blks_read,0)) ) as from_disk, 
        ( (coalesce(heap_blks_hit,0)  + coalesce(idx_blks_hit,0)  + coalesce(toast_blks_hit,0)  + coalesce(tidx_blks_hit,0))  ) as from_cache    
    FROM    pg_statio_all_tables --> change to pg_statio_USER_tables if you want to check only user tables (excluding postgres's own tables)
    ) a
WHERE   (from_disk + from_cache) > 0 -- discard tables without hits
)
SELECT  table_name as "table name",
    from_disk as "disk hits",
    round((from_disk::numeric / (from_disk + from_cache)::numeric)*100.0,2) as "% disk hits",
    round((from_cache::numeric / (from_disk + from_cache)::numeric)*100.0,2) as "% cache hits",
    (from_disk + from_cache) as "total hits"
FROM    (SELECT * FROM all_tables UNION ALL SELECT * FROM tables) a
ORDER   BY (case when table_name = 'all' then 0 else 1 end), from_disk desc
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明