2010-08-06 13 views
6

En PostgreSQL tengo una consulta como la siguiente que eliminará 250k filas de una fila de la tabla 1m:Eliminación de muchas filas sin encerrarlos

DELETE FROM table WHERE key = 'needle'; 

La consulta tarda más de una hora de ejecutar y durante ese tiempo, la las filas afectadas están bloqueadas para escritura. Eso no es bueno porque significa que muchas consultas de actualización tienen que esperar a que se complete la consulta de eliminación grande (y luego fallarán porque las filas desaparecieron debajo de ellos, pero eso está bien). Necesito una forma de segmentar esta gran consulta en varias partes para que causen la menor interferencia posible con las consultas de actualización. Por ejemplo, si la consulta de eliminación se puede dividir en fragmentos, cada uno con 1000 filas en ellos, las otras consultas de actualización a lo sumo tendrán que esperar una consulta de eliminación que involucre 1000 filas.

DELETE FROM table WHERE key = 'needle' LIMIT 10000; 

Esa consulta funcionaría muy bien, pero lamentablemente no existe en postgres.

Respuesta

19

Pruebe una subselección y utilizar una única condición:

DELETE FROM 
    table 
WHERE 
    id IN (SELECT id FROM table WHERE key = 'needle' LIMIT 10000); 
+0

¡Perfecto! (No puedo creer que no haya pensado en esto yo mismo) –

0

Frak's answer es bueno, pero esto puede ser más rápido, pero requiere 8,4 debido al apoyo funciones de la ventana (pseudocódigo):

result = query('select 
    id from (
     select id, row_number(*) over (order by id) as row_number 
     from mytable where key=? 
    ) as _ 
    where row_number%8192=0 order by id', 'needle'); 
// result contains ids of every 8192nd row which key='needle' 
last_id = 0; 
result.append(MAX_INT); // guard 
for (row in result) { 
    query('delete from mytable 
     where id<=? and id>? and key=?', row.id, last_id, 'needle'); 
    // last_id is used to hint query planner, 
    // that there will be no rows with smaller id 
    // so it is less likely to use full table scan 
    last_id = row.id; 
} 

Ésta es la optimización prematura — cosa mala . Tener cuidado.

Cuestiones relacionadas