Tengo que actualizar tablas de 1 o 2 mil millones de filas con varios valores para cada fila. Cada ejecución hace ~100 millones de cambios (10%). Mi primer intento fue agruparlos en una transacción de 300 000 actualizaciones directamente en una partición específica, ya que Postgresql no siempre optimiza las consultas preparadas si usa particiones.
- Las transacciones de un montón de "ACTUALIZAR myTable SET myField=value WHEREmyId=id"
dan 1500 actualizaciones/seg. lo que significa que cada ejecución tomaría al menos 18 horas. - HOT actualiza la solución como se describe aquí con FILLFACTOR=50. Proporciona 1600 actualizaciones/seg. Uso SSD, por lo que es una mejora costosa, ya que duplica el tamaño de almacenamiento.
- Insertar en una tabla temporal de valor actualizado y fusionarlos después con ACTUALIZAR... DESDE Da 18,000 actualizaciones/seg. si hago un VACÍO para cada partición; 100.000 up/s de lo contrario. Genial.
Esta es la secuencia de operaciones:
CREATE TEMP TABLE tempTable (id BIGINT NOT NULL, field(s) to be updated,
CONSTRAINT tempTable_pkey PRIMARY KEY (id));
Acumule un montón de actualizaciones en un búfer dependiendo de la RAM disponible Cuando esté lleno, o necesite cambiar de tabla/partición, o completado:
COPY tempTable FROM buffer;
UPDATE myTable a SET field(s)=value(s) FROM tempTable b WHERE a.id=b.id;
COMMIT;
TRUNCATE TABLE tempTable;
VACUUM FULL ANALYZE myTable;
Eso significa que una ejecución ahora toma 1.5 h en lugar de 18 h para 100 millones de actualizaciones, incluido el vacío. Para ahorrar tiempo, no es necesario realizar un vacío COMPLETO al final, pero incluso un vacío regular rápido es útil para controlar su ID de transacción en la base de datos y no obtener un vacío automático no deseado durante las horas pico.