Estoy cambiando a PostgreSQL desde SQLite para una aplicación típica de Rails.
El problema es que las especificaciones de ejecución se volvieron lentas con PG.
En SQLite tardó ~ 34 segundos, en PG es ~ 76 segundos, que es más de 2 veces más lento .
Así que ahora quiero aplicar algunas técnicas para llevar el rendimiento de las especificaciones a la par con SQLite sin modificaciones de código (idealmente solo configurando las opciones de conexión, lo que probablemente no sea posible).
Un par de cosas obvias desde lo alto de mi cabeza son:
- Disco RAM (sería bueno ver una buena configuración con RSpec en OSX)
- Tablas sin registrar (¿se puede aplicar en toda la base de datos para que no haya cambiado todos los scripts?)
Como habrás entendido, no me importa la confiabilidad y el resto (el DB es solo una cosa desechable aquí).
Necesito aprovechar al máximo el PG y hacerlo lo más rápido posible .
La mejor respuesta ideal sería describir los trucos para hacer exactamente eso, la configuración y los inconvenientes de esos trucos.
ACTUALIZACIÓN: fsync = off
+ full_page_writes = off
solo disminuyó el tiempo a ~ 65 segundos (~ -16 segundos). Buen comienzo, pero lejos del objetivo de 34.
ACTUALIZACIÓN 2: Me trató de disco uso de RAM , pero la ganancia de rendimiento estaba dentro de un margen de error. Así que no parece valer la pena.
ACTUALIZACIÓN 3: * Encontré el mayor cuello de botella y ahora mis especificaciones se ejecutan tan rápido como las SQLite.
El problema fue la limpieza de la base de datos que hizo el truncamiento . Aparentemente, SQLite es demasiado rápido allí.
Para "arreglarlo", abro una transacción antes de cada prueba y la vuelvo al final.
Algunos números para ~ 700 pruebas.
- Truncamiento: SQLite - 34s, PG - 76s.
- Transacción: SQLite - 17s, PG - 18s.
Aumento de velocidad 2x para SQLite. Aumento de velocidad 4x para PG.
fuente
Respuestas:
Primero, use siempre la última versión de PostgreSQL. Las mejoras de rendimiento siempre están llegando, por lo que probablemente esté perdiendo el tiempo si está ajustando una versión anterior. Por ejemplo, PostgreSQL 9.2 mejora significativamente la velocidad
TRUNCATE
y, por supuesto, agrega escaneos de solo índice. Incluso los lanzamientos menores siempre deben seguirse; ver la política de versiones .No hacer
No NO poner un espacio de tabla en un disco RAM u otro almacenamiento no duraderos .
Si pierde un espacio de tabla, toda la base de datos puede dañarse y ser difícil de usar sin un trabajo significativo. Esto tiene muy poca ventaja en comparación con solo usar
UNLOGGED
tablas y tener mucha RAM para caché de todos modos.Si realmente desea un sistema basado en ramdisk,
initdb
un clúster completamente nuevo en el ramdiskinitdb
incorporando una nueva instancia de PostgreSQL en el ramdisk, por lo que tiene una instancia de PostgreSQL completamente desechable.Configuración del servidor PostgreSQL
Al realizar la prueba, puede configurar su servidor para una operación no duradera pero más rápida .
Este es uno de los únicos usos aceptables para la
fsync=off
configuración en PostgreSQL. Esta configuración casi le dice a PostgreSQL que no se moleste con las escrituras ordenadas o cualquiera de esas otras cosas desagradables de protección de integridad de datos y seguridad contra choques, lo que le da permiso para destruir completamente sus datos si pierde energía o tiene un bloqueo del sistema operativo.Huelga decir que nunca debe habilitar la
fsync=off
producción a menos que esté usando Pg como una base de datos temporal para datos que puede volver a generar desde otro lugar. Si y solo si está haciendo para desactivar fsync también se puedefull_page_writes
desactivar, ya que ya no sirve de nada. Tenga cuidadofsync=off
yfull_page_writes
aplique a nivel de clúster , de modo que afecten a todas las bases de datos en su instancia de PostgreSQL.Para el uso de producción, posiblemente pueda usar
synchronous_commit=off
y establecer uncommit_delay
, ya que obtendrá muchos de los mismos beneficios quefsync=off
sin el riesgo de corrupción de datos gigantes. Tiene una pequeña ventana de pérdida de datos recientes si habilita la confirmación asíncrona, pero eso es todo.Si tiene la opción de alterar ligeramente el DDL, también puede usar
UNLOGGED
tablas en la página 9.1+ para evitar completamente el registro de WAL y obtener un aumento de velocidad real a costa de que las tablas se borren si el servidor falla. No hay una opción de configuración para hacer que todas las tablas no se registren, se debe configurar duranteCREATE TABLE
. Además de ser bueno para las pruebas, esto es útil si tiene tablas llenas de datos generados o sin importancia en una base de datos que de lo contrario contiene cosas que necesita para estar seguro.Verifique sus registros y vea si recibe advertencias sobre demasiados puntos de control. Si es así, debe aumentar sus checkpoint_segments . También es posible que desee ajustar su checkpoint_completion_target para suavizar las escrituras.
Sintonice
shared_buffers
para adaptarse a su carga de trabajo. Esto depende del sistema operativo, depende de lo que esté sucediendo con su máquina y requiere algo de prueba y error. Los valores predeterminados son extremadamente conservadores. Es posible que deba aumentar el límite máximo de memoria compartida del sistema operativo si aumentashared_buffers
PostgreSQL 9.2 y versiones inferiores; 9.3 y superior cambió la forma en que usan la memoria compartida para evitar eso.Si está utilizando solo un par de conexiones que hacen mucho trabajo, aumente
work_mem
para darles más RAM para jugar, etc. Tenga en cuenta que unawork_mem
configuración demasiado alta puede causar problemas de falta de memoria porque es por tipo, no por conexión para que una consulta pueda tener muchos tipos anidados. Realmente solo tiene que aumentarwork_mem
si puede ver cómo se derraman tipos en el discoEXPLAIN
o si se registra con lalog_temp_files
configuración (recomendado), pero un valor más alto también puede permitir que Pg elija planes más inteligentes.Como dijo otro póster aquí, es aconsejable colocar el xlog y las tablas / índices principales en discos duros separados si es posible. Las particiones separadas son bastante inútiles, realmente quieres unidades separadas. Esta separación tiene mucho menos beneficio si está ejecutando
fsync=off
y casi ninguno si está utilizandoUNLOGGED
tablas.Finalmente, ajuste sus consultas. Asegúrese de que su
random_page_cost
yseq_page_cost
refleje el rendimiento de su sistema, asegúrese de queeffective_cache_size
sea correcto, etc. UtilíceloEXPLAIN (BUFFERS, ANALYZE)
para examinar planes de consulta individuales y encienda elauto_explain
módulo para informar todas las consultas lentas. A menudo puede mejorar drásticamente el rendimiento de las consultas simplemente creando un índice apropiado o ajustando los parámetros de costo.AFAIK no hay forma de configurar una base de datos completa o un clúster como
UNLOGGED
. Sería interesante poder hacerlo. Considere preguntar en la lista de correo de PostgreSQL.Ajuste del sistema operativo del host
También puede hacer algunos ajustes a nivel del sistema operativo. Lo principal que puede querer hacer es convencer al sistema operativo de que no vacíe las escrituras en el disco de forma agresiva, ya que realmente no le importa cuándo / si llegan al disco.
En Linux se puede controlar esto con el subsistema de memoria virtual 's
dirty_*
ajustes, comodirty_writeback_centisecs
.El único problema con el ajuste de la configuración de reescritura es demasiado flojo es que una descarga de algún otro programa puede hacer que también se vacíen todos los búferes acumulados de PostgreSQL, causando grandes paradas mientras todo se bloquea en las escrituras. Es posible que pueda aliviar esto ejecutando PostgreSQL en un sistema de archivos diferente, pero algunas descargas pueden ser a nivel de dispositivo o a nivel de host completo, no a nivel de sistema de archivos, por lo que no puede confiar en eso.
Esta optimización realmente requiere jugar con la configuración para ver qué funciona mejor para su carga de trabajo.
En los núcleos más nuevos, es posible que desee asegurarse de que
vm.zone_reclaim_mode
esté configurado en cero, ya que puede causar graves problemas de rendimiento con los sistemas NUMA (la mayoría de los sistemas en estos días) debido a las interacciones con la gestión de PostgreSQLshared_buffers
.Consulta y ajuste de carga de trabajo
Estas son cosas que sí requieren cambios de código; Puede que no te convengan. Algunas son cosas que puede aplicar.
Si no está agrupando el trabajo en transacciones más grandes, comience. Muchas pequeñas transacciones son caras, por lo que debe agrupar las cosas siempre que sea posible y práctico. Si está utilizando la confirmación asincrónica, esto es menos importante, pero sigue siendo muy recomendable.
Siempre que sea posible, use tablas temporales. No generan tráfico WAL, por lo que son mucho más rápidos para inserciones y actualizaciones. A veces vale la pena deslizar un montón de datos en una tabla temporal, manipulándola como sea necesario y luego haciendo una
INSERT INTO ... SELECT ...
copia para copiarla en la tabla final. Tenga en cuenta que las tablas temporales son por sesión; si su sesión finaliza o pierde su conexión, la tabla temporal desaparece y ninguna otra conexión puede ver el contenido de las tablas temporales de una sesión.Si está usando PostgreSQL 9.1 o más reciente, puede usar
UNLOGGED
tablas para datos que puede permitirse perder, como el estado de la sesión. Estos son visibles en diferentes sesiones y se conservan entre las conexiones. Se truncan si el servidor se cierra de manera sucia, por lo que no se pueden usar para nada que no se pueda volver a crear, pero son excelentes para cachés, vistas materializadas, tablas de estado, etc.En general, no lo hagas
DELETE FROM blah;
. Usar en suTRUNCATE TABLE blah;
lugar; es mucho más rápido cuando estás volcando todas las filas en una tabla. Trunca muchas tablas en unaTRUNCATE
llamada si puedes. SinTRUNCATES
embargo, hay una advertencia si estás haciendo muchas mesas pequeñas una y otra vez; ver: velocidad de truncamiento PostgresqlSi no tiene índices en claves foráneas, los
DELETE
s que involucren las claves primarias a las que hacen referencia esas claves foráneas serán horriblemente lentos. Asegúrese de crear dichos índices si alguna vez lo esperaDELETE
de las tablas referenciadas. No se requieren índices paraTRUNCATE
.No cree índices que no necesita. Cada índice tiene un costo de mantenimiento. Intente utilizar un conjunto mínimo de índices y deje que los escaneos de índice de mapa de bits los combinen en lugar de mantener demasiados índices enormes y costosos de múltiples columnas. Cuando se requieren índices, primero intente llenar la tabla y luego cree índices al final.
Hardware
Tener suficiente RAM para contener toda la base de datos es una gran victoria si puede administrarlo.
Si no tiene suficiente RAM, cuanto más rápido sea el almacenamiento, mejor. Incluso un SSD barato hace una gran diferencia sobre el óxido giratorio. Sin embargo, no confíe en los SSD baratos para la producción, a menudo no son seguros y pueden comer sus datos.
Aprendizaje
El libro de Greg Smith, PostgreSQL 9.0 High Performance sigue siendo relevante a pesar de referirse a una versión algo más antigua. Debería ser una referencia útil.
Únase a la lista de correo general de PostgreSQL y sígala.
Leyendo:
fuente
Utilice un diseño de disco diferente:
ajustes de postgresql.conf:
fuente
fsync=off
, poner pg_xlog en un disco separado ya no mejora mucho.