2009-06-01 19 views
10

Tengo una tabla DB con 25M filas, ~ 3K cada una (es decir ~ 75GB), que junto con múltiples índices que uso (15-20GB adicionales) no encajar completamente en la memoria (64 GB en la máquina). Una consulta típica localiza 300 filas a través de un índice, opcionalmente las filtra a ~ 50-300 filas utilizando otros índices, y finalmente busca las filas correspondientes. Los tiempos de respuesta varían entre 20ms en un DB cálido a 20 segundos en un DB frío. Tengo dos preguntas relacionadas:Caché Postgresql (memoria) rendimiento + cómo calentar el caché

  1. en un momento dado, ¿cómo puedo comprobar qué parte (%) de las tablas e índices específicos se almacena en caché en la memoria?

  2. ¿Cuál es la mejor manera de calentar la caché antes de abrir la base de datos a las consultas? P.ej. "select *" fuerza un escaneo secuencial (~ 15 minutos en DB frío) pero los tiempos de respuesta siguen siendo pobres. ¿Hay una manera integrada para realizar esta acción en lugar de a través de consultas de un

Gracias, no dude en responder también por correo electrónico ([email protected]])

- Shaul

Respuesta

1

Anuncio. 1 - No tengo absolutamente ninguna idea.

Ad. 2 - ¿por qué no elige aleatoriamente algunas consultas que sabe que son importantes y las ejecuta en un servidor frío? Cuantas más consultas ejecutará, mejor será el proceso de preparación.

2

2) Generalmente resuelvo esto teniendo un registro de consultas de un sistema en vivo y volviéndolo a reproducir. Esto calienta las partes típicas de los datos y no las partes que no se utilizan con tanta frecuencia (lo que de otra manera desperdiciará RAM).

+0

El problema es que no puedo adivinar las consultas de los usuarios, piense en "Amazon": ¿cuáles serán las próximas 10000 consultas? Así que me hubiera gustado ejecutar algo que extraiga tablas e índices específicos en el caché. –

+0

No adivine. Tome un registro real de los últimos 5 minutos o las últimas 10 000 consultas. He trabajado en "un proveedor líder de motores de búsqueda" y esto funciona muy bien. O si tiene servidores en funcionamiento y quiere calentar uno nuevo, puede duplicar las consultas al servidor que se va a calentar. – Thomas

3

En cuanto a su primer punto, el módulo contrib "pg_buffercache" le permite inspeccionar el contenido de la memoria caché del búfer. Me gusta definir esto:

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; 

Además, el módulo contrib "pageinspect" le permite acceder a una página específica de una relación, por lo que supongo que se podría simplemente bucle a través de todas las páginas en una relación que agarrar?

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; 

Esto cargará todos information_schema.sql_features en el caché.

0

No intente calentar la memoria, ese es el trabajo postgresql y el sistema operativo. Simplemente divida tablas (e índices) en particiones y trate de trabajar con conjuntos de datos más pequeños. Si logra establecer un buen plan de partición, entonces no hay problema con los grandes índices o tablas. Si aún desea calentar las tablas y los índices, es posible que se pueda almacenar completamente en la memoria RAM porque son más pequeños que antes.

+0

Creo que el calentamiento y la partición del caché son dos cuestiones distintas. El particionamiento no resuelve el problema inicial de "caché fría". Es un problema de E/S. – Jan

Cuestiones relacionadas