PostgreSQL: fuerza los datos en la memoria


32

¿Hay alguna forma sistemática de obligar a PostgreSQL a cargar una tabla específica en la memoria, o al menos leerla desde el disco para que el sistema la almacene en caché?

Respuestas:


25

Puede estar interesado en uno de los temas de las listas de correo , es respondido por Tom Lane (desarrollador principal):

[..] Pero mi opinión es que las personas que piensan que son más inteligentes que un algoritmo de almacenamiento en caché LRU suelen estar equivocadas. Si la tabla es muy utilizada, permanecerá en la memoria bien. Si no se usa lo suficiente como para permanecer en la memoria de acuerdo con un algoritmo de LRU, tal vez el espacio de memoria realmente debería gastarse en otra cosa. [..]

También podría estar interesado en una pregunta SO: https://stackoverflow.com/questions/486154/postgresql-temporary-tables y tal vez más apta para https://stackoverflow.com/questions/407006/need-to-load-the -whole-postgresql-database-into-the-ram


1
+1 La misma idea se aplica a otros RDBMS también.
gbn

25
Si y no. Bloqueamos algunas tablas de Oracle en la memoria porque sabemos que es posible que no se usen con tanta frecuencia, pero en la situación en que se usan, la latencia será mortal. Un DB siempre debe dar la última palabra al DBA (otro ejemplo es insinuar el optimizador de consultas).
Cayo

35

Postgres 9.4 finalmente agregó una extensión para precargar los datos de las relaciones en el sistema operativo o la memoria caché del búfer de la base de datos (a su elección):

pg_prewarm

Esto permite alcanzar el rendimiento operativo completo más rápidamente.

Ejecute una vez en su base de datos (instrucciones detalladas aquí ):

CREATE EXTENSION pg_prewarm;

Entonces es simple precargar cualquier relación dada. Ejemplo básico:

SELECT pg_prewarm('my_tbl');

Encuentra la primera tabla nombrada my_tblen la ruta de búsqueda y la carga en la memoria caché del búfer de Postgres

O:

SELECT pg_prewarm('my_schema.my_tbl', 'prefetch');

prefetchemite solicitudes de captación previa asincrónicas al sistema operativo, si esto es compatible, o arroja un error de lo contrario. read lee el rango de bloques solicitado; a diferencia prefetch, esto es sincrónico y compatible con todas las plataformas y compilaciones, pero puede ser más lento. bufferlee el rango de bloques solicitado en la memoria caché del búfer de la base de datos.

El valor predeterminado es buffer, que tiene el mayor impacto (mayor costo, mejor efecto).

Lea el manual para más detalles , las citas son de allí.
Depesz también blogueó al respecto.


4

En el caso general, si tiene suficiente RAM, generalmente puede confiar en el servicio de base de datos para hacer un buen trabajo al mantener las cosas que usa regularmente en la RAM. Algunos sistemas le permiten insinuar que la tabla siempre debe mantenerse en la RAM (lo cual es útil para las tablas más pequeñas que no se usan con frecuencia, pero cuando se usan es importante que respondan lo más rápido posible), pero si pgsql tiene tales sugerencias de tabla debe tener mucho cuidado al usarlos, ya que está reduciendo la cantidad de memoria disponible para almacenar en caché cualquier otra cosa, por lo que podría ralentizar su aplicación en general.

Si está buscando cebar la memoria caché de la página de la base de datos al inicio (por ejemplo, después de un reinicio u otra operación de mantenimiento que hace que la base de datos olvide todo lo que está en caché), escriba un script que haga lo siguiente:

SELECT * FROM <table>
SELECT <primary key fields> FROM <table> ORDER BY <primary key fields>
SELECT <indexed fields> FROM <table> ORDER BY <indexed fields>

(ese último paso se repite para cada índice o curso, y tenga cuidado de tener los campos en la cláusula ORDER BY en el orden correcto)

Después de ejecutar lo anterior, todas las páginas de datos e índices deberían haberse leído y, por lo tanto, estarán en la memoria caché de la página RAM (al menos por el momento). Tenemos scripts como este para nuestras bases de datos de aplicaciones, que se ejecutan después del reinicio para que los primeros usuarios que inicien sesión en el sistema no experimenten una respuesta más lenta. Es mejor escribir a mano cualquier script de este tipo, en lugar de escanear las tablas de definición de base de datos (como sys.objects/ sys.indexes/ sys.columnsen MSSQL), luego puede escanear selectivamente los índices que se usan más comúnmente en lugar de escanear todo lo que llevará más tiempo.


3
Esto no funcionará, al menos en PostgreSQL. Se asigna un búfer de anillo pequeño (256 KB) de búferes compartidos para exploraciones secuenciales para evitar que se use todo el caché de búfer. Ver github.com/postgres/postgres/blob/master/src/backend/storage/… para más detalles. Puede verificar esto haciendo un SELECT * desde una tabla grande y luego mirando la tabla pg_buffercache (desde la extensión pg_buffercache).
hbn

@hbn hola, pero este tipo en este hilo de guardado dice que funciona: dba.stackexchange.com/a/36165/55752
scythargon

@scythargon podría terminar en el caché del sistema operativo, no lo conseguirá en el caché del búfer de PostgreSQL. Prueba lo que te sugerí anteriormente si no me crees.
hbn

En Postgres 9.5, probé SELECT * FROM schema.tabley vi que cargaba toda la tabla de 60GiB en mi caché de búfer PostgreSQL de 100GiB.
sudo

1

Tuve un problema similar:
después de reiniciar el servicio del servidor y todos los datos cobrados cayeron, muchas consultas se llamaron por primera vez donde realmente realmente lento, debido a la complejidad específica de las consultas, hasta que se cobraron todos los índices y datos necesarios. eso significa que, por ejemplo, los usuarios deben presionar una vez cada "elemento" (tiempo de ejecución de 1-3 segundos) y datos relacionados de 50 millones de filas, para que los usuarios ya no experimenten demoras no deseadas. A los usuarios les toma las primeras 3 horas experimentar bloqueos molestos, hasta que se cobra la mayoría de los datos utilizados y los programas están arruinando la mejor calidad con el rendimiento de la producción, finalizan incluso entonces, 2 días, algunos retrasos breves y repentinos, cuando se obtienen menos datos a los que se accede por primera vez ... , para datos estadísticos, etc.

Para resolver esto, escribí una pequeña secuencia de comandos de Python que realiza selecciones en las tablas más pesadas con índices grandes. Tardó 15 minutos en ejecutarse y no hubo retrasos en el rendimiento.


0

Hmmm, puede ser que el comando COPY ayudaría. Simplemente ejecute COPY a stdout y lea de él. Es posible hacerlo usando pg_dump:

pg_dump -U <user> -t <table> <database> > /dev/null

Otra forma es encontrar todos los archivos de tabla y ejecutarlos cat <files> > /dev/null.

Aquí está el ejemplo sobre cómo obtener nombres de archivos de tabla:

# SELECT oid, datname FROM pg_database ;
  oid  |  datname  
-------+-----------                                                                                                                                          
<...>
 16384 | test
-- out of database is 16384
# SELECT oid, relname FROM pg_class WHERE relname like 'fn%';
  oid  | relname 
-------+---------
 24576 | fn
(1 row)
-- oid of our table is 24576

entonces, los archivos de la tabla son / ruta / a / pgsql / data / base / 16384/24576 *

Usted también quiere leer índices y tablas de tostados, obtener sus oids de la misma manera.

Por cierto, ¿por qué lo necesitas? Creo que postgresql y OS son lo suficientemente inteligentes como para almacenar en caché los datos más actuales y mantenerlos bien. Eficiencia de caché.


0

Uso RamDrive de QSoft, que fue comparado como el disco RAM más rápido para Windows. Acabo de usar

initdb -D e:\data

donde e: \ es el lugar del RamDisk.


55
PG en Windows es una opción bastante valiente para un sitio de producción, ya que es mucho más lento en Windows que en * nix (independiente de la RAM).
DrColossos
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.