2009-06-01 118 views
10

我有一個25M行的DB表,每個〜3K(即〜75GB),與我使用的多個索引(額外的15-20GB)一起不會完全適合內存(機器上64GB)。典型的查詢通過索引定位300行,可選地使用其他索引將它們過濾到約50-300行,最後獲取匹配的行。響應時間在溫暖的DB上20ms到冷DB上的20秒之間變化。我有兩個相關的問題:Postgresql緩存(內存)性能+如何預熱緩存

  1. 在任何時候我怎麼能檢查特定表和索引的什麼部分(%)在內存中緩存?

  2. 在打開數據庫查詢之前預熱高速緩存的最佳方法是什麼?例如。 「select *」強制進行順序掃描(在冷DB上約15分鐘),但其後的響應時間仍然很差。是否有一個內置的方式做到這一點,而不是通過查詢一個

謝謝,隨便也通過電子郵件回覆([email protected]])

- 沙烏爾

回答

1

廣告。 1 - 我完全沒有理想。

Ad。 2 - 爲什麼不隨意選擇一些你知道重要的查詢,然後在冷服務器上運行它們?您運行的查詢越多,熱身過程就越好。

2

2)我通常通過查詢來自實時系統的查詢並重播它們來解決此問題。這會加熱數據的典型部分,而不是那些不經常使用的部分(否則會浪費RAM)。

+0

問題是我無法猜測用戶的查詢,認爲「亞馬遜」 - 接下來的10000個查詢會是什麼?所以我會喜歡運行一些將特定表和索引拖入緩存的東西。 – 2009-06-01 12:55:16

+0

不要猜測。從最近5分鐘或最近10'000個查詢中獲取實際日誌。我曾在「一家領先的搜索引擎提供商」工作,這很好。 或者,如果您的服務器已啓動並正在運行,並且您想預熱新服務器,則可以將查詢鏡像到要預熱的服務器。 – Thomas 2009-06-01 19:59:52

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中,因爲比以前小。