sql >> Base de Datos >  >> RDS >> PostgreSQL

Cómo acelerar el rendimiento de inserción en PostgreSQL

Consulte poblar una base de datos en el manual de PostgreSQL, el excelente artículo habitual de depesz sobre el tema y esta pregunta SO.

(Tenga en cuenta que esta respuesta trata sobre la carga masiva de datos en una base de datos existente o para crear una nueva. Si está interesado, restaure el rendimiento de la base de datos con pg_restore o psql ejecución de pg_dump salida, gran parte de esto no se aplica desde pg_dump y pg_restore ya hace cosas como crear activadores e índices después de que finaliza una restauración de esquema+datos) .

Hay mucho por hacer. La solución ideal sería importar a un UNLOGGED tabla sin índices, luego cámbiela a registrada y agregue los índices. Desafortunadamente, en PostgreSQL 9.4 no hay soporte para cambiar tablas de UNLOGGED para iniciar sesión 9.5 agrega ALTER TABLE ... SET LOGGED para permitirle hacer esto.

Si puede desconectar su base de datos para la importación masiva, use pg_bulkload .

De lo contrario:

  • Deshabilita cualquier disparador en la mesa

  • Suelte los índices antes de iniciar la importación, vuelva a crearlos después. (Se necesita mucho menos tiempo para crear un índice de una sola pasada que para agregarle los mismos datos progresivamente, y el índice resultante es mucho más compacto).

  • Si realiza la importación dentro de una sola transacción, es seguro eliminar las restricciones de clave externa, realizar la importación y volver a crear las restricciones antes de confirmar. No haga esto si la importación se divide en varias transacciones, ya que podría introducir datos no válidos.

  • Si es posible, use COPY en lugar de INSERT s

  • Si no puede usar COPY considere usar INSERT de varios valores s si es práctico. Parece que ya lo estás haciendo. No intente incluir también muchos valores en un solo VALUES aunque; esos valores tienen que caber en la memoria un par de veces, así que manténgalo en unos pocos cientos por declaración.

  • Combine sus inserciones en transacciones explícitas, haciendo cientos de miles o millones de inserciones por transacción. AFAIK no existe un límite práctico, pero el procesamiento por lotes le permitirá recuperarse de un error al marcar el inicio de cada lote en sus datos de entrada. De nuevo, parece que ya lo estás haciendo.

  • Usa synchronous_commit=off y un gran commit_delay para reducir los costos de fsync(). Sin embargo, esto no ayudará mucho si ha agrupado su trabajo en grandes transacciones.

  • INSERT o COPY en paralelo desde varias conexiones. Cuántos depende del subsistema de disco de su hardware; como regla general, desea una conexión por disco duro físico si usa almacenamiento adjunto directo.

  • Establecer un alto max_wal_size valor (checkpoint_segments en versiones anteriores) y habilite log_checkpoints . Mire los registros de PostgreSQL y asegúrese de que no se queje de que los puntos de control ocurren con demasiada frecuencia.

  • Si y solo si no le importa perder todo su clúster PostgreSQL (su base de datos y cualquier otra en el mismo clúster) debido a una corrupción catastrófica si el sistema falla durante la importación, puede detener Pg, establecer fsync=off , inicie Pg, haga su importación, luego (muy importante) detenga Pg y establezca fsync=on otra vez. Ver configuración WAL. No haga esto si ya hay datos que le interesen en alguna base de datos en su instalación de PostgreSQL. Si configura fsync=off también puede configurar full_page_writes=off; nuevamente, solo recuerde volver a encenderlo después de su importación para evitar la corrupción de la base de datos y la pérdida de datos. Consulte los ajustes no duraderos en el manual de Pg.

También debe considerar ajustar su sistema:

  • Utilice buena calidad SSD para almacenamiento tanto como sea posible. Los buenos SSD con cachés de reescritura confiables y protegidos de energía hacen que las tasas de confirmación sean increíblemente más rápidas. Son menos beneficiosos cuando sigue los consejos anteriores, que reducen los vaciados de disco / número de fsync() s - pero todavía puede ser de gran ayuda. No utilice SSD económicos sin la protección adecuada contra fallas de energía a menos que no le importe conservar sus datos.

  • Si está utilizando RAID 5 o RAID 6 para almacenamiento adjunto directo, deténgase ahora. Realice una copia de seguridad de sus datos, reestructure su matriz RAID a RAID 10 y vuelva a intentarlo. RAID 5/6 es inútil para el rendimiento de escritura masiva, aunque un buen controlador RAID con un gran caché puede ayudar.

  • Si tiene la opción de usar un controlador RAID de hardware con una gran caché de reescritura respaldada por batería, esto realmente puede mejorar el rendimiento de escritura para cargas de trabajo con muchas confirmaciones. No es de mucha ayuda si está utilizando una confirmación asíncrona con un commit_delay o si está realizando menos transacciones grandes durante la carga masiva.

  • Si es posible, almacene WAL (pg_wal o pg_xlog en versiones anteriores) en un disco/matriz de discos separado. No tiene mucho sentido usar un sistema de archivos separado en el mismo disco. La gente a menudo elige usar un par RAID1 para WAL. Una vez más, esto tiene más efecto en los sistemas con altas tasas de confirmación y tiene poco efecto si está utilizando una tabla no registrada como destino de carga de datos.

También puede estar interesado en Optimize PostgreSQL para pruebas rápidas.