Me pregunto cuál sería la forma más eficiente de eliminar grandes cantidades de filas de PostgreSQL, este proceso sería parte de una tarea recurrente todos los días para importar datos en masa (un delta de inserciones + eliminaciones) en una tabla. Podría haber miles, potencialmente millones de filas para eliminar.
Tengo un archivo de claves principales, una por línea. Las dos opciones en las que estaba pensando estaban en la línea de abajo, pero no conozco / entiendo lo suficiente de lo interno de PostgreSQL para tomar una decisión informada que sería lo mejor.
- Ejecute una
DELETE
consulta para cada fila en el archivo, con una simpleWHERE
clave primaria (o agrupe las eliminaciones en lotes paran
usar unaIN()
cláusula) - Importe las claves primarias en una tabla temporal con el
COPY
comando y luego elimínelas de la tabla principal con una combinación
¡Cualquier sugerencia será muy apreciada!
postgresql
delete
bulk
Tarnfeld
fuente
fuente
Respuestas:
Su segunda opción es mucho más limpia y funcionará lo suficientemente bien como para que valga la pena. Su alternativa es crear consultas gigantescas que serán bastante difíciles de planificar y ejecutar. En general, será mejor dejar que PostgreSQL haga el trabajo aquí. En general, he encontrado actualizaciones en decenas de miles de filas en la forma en que estás describiendo que funcionan adecuadamente, pero hay una cosa importante que debes evitar.
La forma de hacerlo es usar una selección y una combinación en su eliminación.
Bajo ninguna circunstancia debe hacer lo siguiente con una tabla grande:
Esto generalmente causará un bucle anidado antiunión que hará que el rendimiento sea bastante problemático. Si terminas teniendo que ir por esa ruta, haz esto en su lugar:
PostgreSQL generalmente es bastante bueno para evitar malos planes, pero todavía hay casos que involucran uniones externas que pueden hacer una gran diferencia entre los buenos y los malos planes.
Esto está vagando un poco más lejos, pero creo que vale la pena mencionarlo por lo fácil que es pasar de IN a NOT IN y ver el tanque de rendimiento de consultas.
fuente
IN ( select id from foo except select id from rows_to_keep )
ver postgresql.org/docs/9.4/static/queries-union.htmlEncontré esta pregunta porque tenía un problema similar. Estoy limpiando una base de datos que tiene más de 300 millones de filas, la base de datos final solo tendrá alrededor del 30% de los datos originales. Si se enfrenta a un escenario similar, en realidad es más fácil insertar en una nueva tabla y volver a indexar en lugar de eliminar.
Hacer algo como
Con una indexación adecuada en foo y bar, puede evitar los escaneos Seq.
Entonces tendría que volver a indexar y cambiar el nombre de la tabla.
fuente