2009-06-01 6 views
10

나는 25M 행, ~ 3K 각각 (즉 ~ 75GB)의 DB 테이블을 가지고 있으며, 여러 인덱스 (추가 15-20GB)와 함께 사용하면 메모리에 완전히 맞춰집니다 (컴퓨터에서는 64GB). 일반적인 쿼리는 인덱스를 통해 300 개의 행을 찾으며 선택적으로 다른 인덱스를 사용하여 ~ 50-300 행까지 필터링하여 최종적으로 일치하는 행을 가져옵니다. 응답 시간은 콜드 DB에서 20 초 ~ 20 초 사이입니다. 두 가지 관련 질문이 있습니다.Postgresql 캐시 (메모리) 성능 + 캐시 워밍업

  1. 언제든지 특정 테이블과 색인의 어떤 부분 (%)이 메모리에 캐시되어 있는지 확인할 수 있습니까?

  2. DB를 쿼리로 열기 전에 캐시를 워밍업하는 가장 좋은 방법은 무엇입니까? 예 : "select *"는 순차적 검색을 강제 실행하지만 (차가운 DB에서는 약 15 분) 응답 시간은 여전히 ​​나쁩니다. 이 작업을 수행하는 대신 쿼리를 통해 할 수있는 기본 방법이된다

덕분에, 이메일로 회신 해 ([email protected]])

- 사울

답변

1

광고. 1 - 나는 절대적으로 이상이 없다.

광고. 2 - 중요하다고 알고있는 일부 쿼리를 무작위로 선택하고 콜드 서버에서 실행하는 것이 어떻습니까? 실행 쿼리가 많을수록 워밍업 프로세스가 더 좋습니다.

2

2) 일반적으로 라이브 시스템의 쿼리 로그를 재생하여이를 해결합니다. 이렇게하면 자주 사용되지 않는 부분 (RAM을 낭비 할 수 있음)이 아닌 데이터의 일반적인 부분이 예열됩니다.

+0

문제는 "아마존"이라고 생각하는 사용자의 쿼리를 추측 할 수 없다는 것입니다. 다음 10000 개의 쿼리는 무엇이 될까요? 그래서 특정 테이블과 인덱스를 캐시로 가져 오는 것을 실행하고 싶었을 것입니다. –

+0

짐작하지 마십시오. 지난 5 분간의 실제 로그를 보거나 지난 10,000 개의 쿼리를 가져옵니다. 나는 "최고의 검색 엔진 제공 업체"에서 일했으며 훌륭한 결과를 얻었습니다. 또는 실행중인 서버가 있고 새 서버를 예열하려는 경우 예열 할 서버에 쿼리를 미러링 할 수 있습니다. – Thomas

3

첫 번째 포인트에 대해서는 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이 모두로드됩니다.

0

메모리 워밍업을 시도하지 마십시오. postgresql 및 OS 작업입니다. 파티션에서 테이블 (및 인덱스)을 나누고 더 작은 데이터 세트로 작업하십시오. 좋은 파티셔닝 계획을 세우기 위해 성취했다면 거대한 인덱스 나 테이블에는 문제가 없습니다. 테이블과 인덱스를 워밍업하고 싶다면 이전보다 작기 때문에 RAM에 캐시 할 수 있습니다.

+0

캐시 온난화와 파티셔닝은 두 가지 뚜렷한 문제라고 생각합니다. 파티셔닝은 초기 "콜드 캐시"문제를 해결하지 못합니다. 그것은/O 문제입니다. – Jan