J'essaie de porter certaines anciennes requêtes MySQL vers PostgreSQL, mais j'ai des problèmes avec celle-ci:
DELETE FROM logtable ORDER BY timestamp LIMIT 10;
PostgreSQL n'autorise pas l'ordre ou les limites dans sa syntaxe de suppression, et la table n'a pas de clé primaire, je ne peux donc pas utiliser de sous-requête. De plus, je souhaite conserver le comportement où la requête supprime exactement le nombre ou les enregistrements donnés - par exemple, si la table contient 30 lignes mais qu'elles ont toutes le même horodatage, je souhaite toujours supprimer 10, même si cela n'a pas d'importance dont 10.
Alors; comment supprimer un nombre fixe de lignes avec tri dans PostgreSQL?
Modifier: aucune clé primaire signifie qu'il n'y a pas de log_id
colonne ou similaire. Ah, les joies des systèmes hérités!
la source
alter table foo add column id serial primary key
.Réponses:
Vous pouvez essayer d'utiliser le
ctid
:Le
ctid
est:Il y a aussi
oid
mais cela n'existe que si vous le demandez spécifiquement lorsque vous créez la table.la source
VACUUM FULL
ou autovacuum pose des problèmes s'ils modifient lesctid
valeurs de la table pendant l'exécution de la requête?ctid
documentation est qu'ellectid
est suffisamment stable pour que ce DELETE fonctionne correctement mais pas assez stable pour, par exemple, mettre dans une autre table en tant que ghetto-FK. Vraisemblablement, vous ne METTEZ PAS À JOUR le,logtable
donc vous n'avez pas à vous soucier de ce changement dectid
s etVACUUM FULL
verrouillez la table ( postgresql.org/docs/current/static/routine-vacuuming.html ) donc vous n'avez pas à vous soucier de l’autre façon quictid
peut changer. PostgreSQL-Fu de @ araqnid est assez fort et la documentation est d'accord avec lui pour démarrer.La documentation PostgreSQL recommande d'utiliser un tableau au lieu de IN et de sous-requête. Cela devrait fonctionner beaucoup plus rapidement
Ceci et quelques autres astuces peuvent être trouvés ici
la source
any (array( ... ));
c'est plus rapide quein ( ... )
cela ressemble à un bogue dans l'optimiseur de requêtes - il devrait être capable de repérer cette transformation et de faire la même chose avec les données elles-mêmes.IN
sur unUPDATE
(ce qui pourrait être la différence).la source
En supposant que vous souhaitiez supprimer 10 enregistrements (sans la commande), vous pouvez le faire:
Pour mon cas d'utilisation, la suppression de 10 millions d'enregistrements s'est avérée plus rapide.
la source
Vous pouvez écrire une procédure qui boucle sur la suppression pour des lignes individuelles, la procédure peut prendre un paramètre pour spécifier le nombre d'éléments que vous souhaitez supprimer. Mais c'est un peu exagéré par rapport à MySQL.
la source
Si vous n'avez pas de clé primaire, vous pouvez utiliser la syntaxe du tableau Where IN avec une clé composite.
Cela a fonctionné pour moi.
la source