2011-03-02 10 views
60

estoy tratando de puerto de algunos viejos consultas MySQL a PostgreSQL, pero tengo problemas con éste:¿Cómo elimino un número fijo de filas con clasificación en PostgreSQL?

DELETE FROM logtable ORDER BY timestamp LIMIT 10; 

PostgreSQL no permite ordenar o límites en su sintaxis de eliminación, y la mesa doesn' Tengo una clave principal, así que no puedo usar una subconsulta. Además, quiero conservar el comportamiento donde la consulta borra exactamente el número o los registros dados; por ejemplo, si la tabla contiene 30 filas pero todas tienen la misma marca de tiempo, aún quiero eliminar 10, aunque no es así. t materia que 10.

So; ¿Cómo elimino un número fijo de filas con clasificación en PostgreSQL?

Editar: No hay clave primaria significa que no hay log_id columna o similar. ¡Ah, las alegrías de los sistemas heredados!

+1

¿Por qué no agregar la clave principal? Pieza o 'cake en postgresql: 'alter table foo add column id serial primary key'. –

+0

Ese fue mi enfoque inicial, pero otros requisitos lo impiden. – Whatsit

Respuesta

98

Usted podría tratar de usar la ctid:

DELETE FROM logtable 
WHERE ctid IN (
    SELECT ctid 
    FROM logtable 
    ORDER BY timestamp 
    LIMIT 10 
) 

El ctid es:

El ubicación física de la versión de fila dentro de su tabla. Tenga en cuenta que aunque el ctid se puede utilizar para ubicar la versión de la fila muy rápidamente, una fila ctid cambiará si se actualiza o se mueve por VACUUM FULL. Por lo tanto, ctid es inútil como un identificador de fila a largo plazo.

También existe oid pero solo existe si lo solicita específicamente cuando crea la tabla.

+0

Esto funciona, pero ¿qué tan confiable es? ¿Hay alguna 'trampas' que debo tener en cuenta? ¿Es posible que 'VACUUM FULL' o autovacuum cause problemas si cambian los valores' ctid' en la tabla mientras se está ejecutando la consulta? – Whatsit

+2

VACUUM incrementales no cambiarán ctids, no creo. Como eso solo se compara dentro de cada página, y el ctid es solo el número de línea, no un desplazamiento de página. Una operación VACUUM FULL o CLUSTER * * cambiaría la ctid, pero esas operaciones toman primero un bloqueo exclusivo de acceso en la tabla. – araqnid

+0

@Whatsit: Mi impresión de la documentación de 'ctid' es que' ctid' es lo suficientemente estable como para hacer que este DELETE funcione bien pero no lo suficientemente estable como para ponerlo, por ejemplo, en otra tabla como ghetto-FK. Es de suponer que no ACTUALIZAR el 'logtable' por lo que no tiene que preocuparse de que el cambio de' ctid's y 'VACUUM FULL' no bloquee la tabla (http://www.postgresql.org/docs/current/static /routine-vacuuming.html) para que no tenga que preocuparse por la otra forma en que 'ctid's puede cambiar. El PostgreSQL-Fu de @raqnid es bastante fuerte y los documentos están de acuerdo con él para arrancar. –

1

Puede escribir un procedimiento que pase por encima de la eliminación para líneas individuales, el procedimiento podría tomar un parámetro para especificar el número de elementos que desea eliminar. Pero eso es un poco exagerado en comparación con MySQL.

10
delete from logtable where log_id in (
    select log_id from logtable order by timestamp limit 10); 
26

Postgres se recomienda utilizar matriz en lugar de IN y subconsulta. Esto debe trabajar mucho más rápido

DELETE FROM logtable 
WHERE id = any (array(SELECT id FROM logtable ORDER BY timestamp LIMIT 10)); 

Este y algunos otros trucos se pueden encontrar here

+1

No me opongo, ¿pero puede compartir un enlace a estos documentos? –

+0

@Konrad Garus Aquí tienes [link] (http://www.postgres.cz/index.php/PostgreSQL_SQL_Tricks), 'Rápido n primeras filas eliminando' – criticus

+2

Esos no son documentos oficiales, ¿o sí? – jmiserez

2

Suponiendo que quiere eliminar cualquiera de los 10 registros (sin el pedido) usted puede hacer esto:

DELETE FROM logtable as t1 WHERE t1.ctid < (select t2.ctid from logtable as t2 where (Select count(*) from logtable t3 where t3.ctid < t2.ctid) = 10 LIMIT 1); 

Por mi caso de uso, la eliminación de registros 10M, esto resultó ser más rápido.

Cuestiones relacionadas