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)