Postgresql缓存(内存)性能+如何预热缓存

时间:2009-06-01 11:03:59

标签: postgresql

我有一个25M行的DB表,每行约3K(即~75GB),与我使用的多个索引(额外的15-20GB)一起不能完全适合内存(机器上64GB)。典型查询通过索引定位300行,可选地使用其他索引将它们过滤到~50-300行,最后获取匹配的行。响应时间在暖DB上20ms到冷DB上20秒之间变化。我有两个相关的问题:

  1. 在任何给定时间,我如何检查特定表和索引的哪个部分(%)缓存在内存中?

  2. 在打开数据库查询之前预热缓存的最佳方法是什么?例如。 “select *”强制执行顺序扫描(冷DB上约15分钟),但其后的响应时间仍然很短。是否有内置的方法来执行此操作而不是通过查询?a

  3. 谢谢,也可以通过电子邮件回复(info@shauldar.com))

    - Shaul

4 个答案:

答案 0 :(得分:5)

关于第一点,contrib模块“pg_buffercache”允许您检查缓冲区缓存的内容。我想定义一下:

create or replace view util.buffercache_hogs as
select case
       when pg_buffercache.reldatabase = 0
            then '- global'
       when pg_buffercache.reldatabase <> (select pg_database.oid from pg_database where pg_database.datname = current_database())
            then '- database ' || quote_literal(pg_database.datname)
       when pg_namespace.nspname = 'pg_catalog'
            then '- system catalogues'
       when pg_class.oid is null and pg_buffercache.relfilenode > 0
            then '- unknown file ' || pg_buffercache.relfilenode
       when pg_namespace.nspname = 'pg_toast' and pg_class.relname ~ '^pg_toast_[0-9]+$'
            then (substring(pg_class.relname, 10)::oid)::regclass || ' TOAST'::text
       when pg_namespace.nspname = 'pg_toast' and pg_class.relname ~ '^pg_toast_[0-9]+_index$'
            then ((rtrim(substring(pg_class.relname, 10), '_index'))::oid)::regclass || ' TOAST index'
       else pg_class.oid::regclass::text
       end as key,
       count(*) as buffers, sum(case when pg_buffercache.isdirty then 1 else 0 end) as dirty_buffers,
       round(count(*) / (SELECT pg_settings.setting FROM pg_settings WHERE pg_settings.name = 'shared_buffers')::numeric, 4) as hog_factor
from pg_buffercache
     left join pg_database on pg_database.oid = pg_buffercache.reldatabase
     left join pg_class on pg_class.relfilenode = pg_buffercache.relfilenode
     left join pg_namespace on pg_namespace.oid = pg_class.relnamespace
group by 1
order by 2 desc;

此外,“pageinspect”contrib模块允许您从关系中访问特定页面,所以我想您可以简单地遍历抓取它们的关系中的所有页面?

select count(get_raw_page('information_schema.sql_features', n))
from generate_series(0,
        (select relpages-1 from pg_class where relname = 'sql_features')) n;

这会将所有information_schema.sql_features加载到缓存中。

答案 1 :(得分:2)

2)我通常通过记录来自实时系统的查询并重放它来解决这个问题。这样可以预热数据的典型部分,而不是那些不经常使用的部分(否则会浪费RAM)。

答案 2 :(得分:1)

广告。 1 - 我绝对没有想法。

广告。 2 - 为什么不随机选择一些你知道重要的查询,并在冷服务器上运行它们?你运行的查询越多,预热过程就越好。

答案 3 :(得分:0)

不要尝试预热内存,这是postgresql和OS工作。只需在分区中划分表(和索引),并尝试使用较小的数据集。如果您完成了建立良好的分区计划,那么巨大的索引或表就没有问题。如果你仍然想要预热表和索引,那么可以在RAM中完全缓存,因为它比以前更小。