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


11

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


8
无需检查,您始终需要更多RAM。:)
Alex Howansky 2012年

1
不是编程问题,我投票将其移至ServerFault。
GManNickG 2012年

1
我不是DBA,但首先会看到所有常见查询都处于哈希联接的边缘,而不是合并嵌套循环。您可以执行一些数据库配置调整,这可能会影响任何特定查询的可用内存量[检查文档或通过电子邮件发送邮件列表是我的建议]。查看您是否有足够的RAM来保留常用表的缓存也很有用。但是最终,除非您的ENTIRE DB适合RAM,否则您可以使用更多。:)

Answers:


14

如果全部都在Linux上,则总物理RAM应大于磁盘上的数据库大小,以最大程度地减少I / O。最终,整个数据库将位于操作系统读取缓存中,而I / O将仅限于将更改提交到磁盘。我更喜欢通过运行“ du -shc $ PGDATA / base”来找到数据库大小,该方法将所有数据库聚合为一个数字。只要您大于此范围,就可以了。

此外,您可以查看堆和索引块访存的高速缓存命中率。这些度量了PostgreSQL共享缓冲区的命中率。这些数字可能会引起误解-即使共享缓冲区高速缓存中可能遗漏了一些数据,但在操作系统读取高速缓存中仍然有一定的损失。尽管如此,共享缓冲区中的命中仍然比OS读缓存中的命中便宜(后者又比必须返回磁盘便宜了几个数量级)。

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

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;

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

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

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


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

在此处输入图片说明


1

如Heroku doc中所述,它也可以工作:

SELECT
    'cache hit rate' AS name,
     sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) AS ratio
FROM pg_statio_user_tables;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.