J'essaie de porter d'anciennes requêtes MySQL sur PostgreSQL, mais j'ai des problèmes avec celui-ci:
DELETE FROM logtable ORDER BY timestamp LIMIT 10;
PostgreSQL ™ n'autorise pas l'ordre ou les limites dans sa syntaxe de suppression, et le tableau n'a pas de clé primaire, donc je ne peux pas utiliser de sous-requête. En outre, je souhaite préserver le comportement de suppression de la requête exactement du nombre donné ou des enregistrements - par exemple, si la table contient 30 lignes mais qu'elles ont toutes le même horodatage, je souhaite néanmoins supprimer 10, bien que peu importe lequel 10.
Alors; comment puis-je supprimer un nombre fixe de lignes avec le tri dans PostgreSQL?
Edit: Pas de clé primaire signifie qu'il n'y a pas de colonne log_id
ou similaire. Ah, les joies des systèmes hérités!
Vous pouvez essayer d'utiliser ctid
:
DELETE FROM logtable
WHERE ctid IN (
SELECT ctid
FROM logtable
ORDER BY timestamp
LIMIT 10
)
La ctid
est:
L'emplacement physique de la version de la ligne dans sa table. Notez que bien que la variable
ctid
puisse être utilisée pour localiser très rapidement la version de la ligne, la variablectid
d’une ligne sera modifiée si elle est mise à jour ou déplacée parVACUUM FULL
. Par conséquent,ctid
est inutile en tant qu'identificateur de ligne à long terme.
Il y a aussi oid
mais cela n'existe que si vous le demandez spécifiquement lorsque vous créez la table.
Les documents Postgres recommandent d'utiliser array au lieu de IN et de sous-requête. Cela devrait fonctionner beaucoup plus vite
DELETE FROM logtable
WHERE id = any (array(SELECT id FROM logtable ORDER BY timestamp LIMIT 10));
Ceci et quelques autres astuces peuvent être trouvés ici
delete from logtable where log_id in (
select log_id from logtable order by timestamp limit 10);
En supposant que vous vouliez effacer 10 enregistrements (sans ordre), vous pouvez le faire:
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);
Pour mon cas d'utilisation, la suppression de 10 millions d'enregistrements s'est avérée plus rapide.
Vous pouvez écrire une procédure qui effectue une boucle sur la suppression pour des lignes individuelles. Elle peut également prendre un paramètre pour spécifier le nombre d’éléments à supprimer. Mais c'est un peu exagéré par rapport à MySQL.
Si vous n'avez pas de clé primaire, vous pouvez utiliser la syntaxe array Where où IN avec une clé composite.
delete from table1 where (schema,id,lac,cid) in (select schema,id,lac,cid from table1 where lac = 0 limit 1000);
Cela a fonctionné pour moi.