Mise à jour TRÈS GRANDE base de données PostgreSQL table efficacement
J'ai une très grande table de base de données PostgresQL et une colonne comme "copié". Chaque nouvelle ligne commence uncopied et sera plus tard être répliqué à autre chose par un arrière-plan programm. Il y a un index partiel sur la table "btree(ID) OÙ répliqué=0". L'arrière-plan programm fait une sélection de plus de 2000 entrées (LIMITE de 2000), la travaille et puis valide les modifications en une seule opération à l'aide de 2000 sql préparée-commandes.
Maintenant, le problème ist que je veux donner à l'utilisateur une option pour réinitialiser ce répliqué-valeur, faites tout de zéro à nouveau.
Une mise à jour de la table de jeu répliqué=0;
n'est pas possible:
- Il prend beaucoup de temps
- Il double la taille de la table en raison de MVCC
- C'est fait en une seule transaction: Elle manque ou passe à travers.
Je n'ai absolument pas besoin de la transaction de fonctionnalités pour ce cas: Si le système tombe en panne, il doit la traiter seulement des parties.
Plusieurs autres problèmes:
Faire un
update set replicated=0 where id >10000 and id<20000
est aussi mauvais: Il fait un balayage séquentiel de tous sur l'ensemble de la table qui est trop lent.
Si elle ne le faisaient pas, il serait toujours lent, car il serait trop cherche.
Ce que j'ai vraiment besoin, c'est une manière de passer à travers toutes les lignes, de les changer et de ne pas être lié à un géant de la transaction.
Étrange, un
UPDATE table
SET replicated=0
WHERE ID in (SELECT id from table WHERE replicated= LIMIT 10000)
est aussi lent, mais il devrait être une bonne chose: Passer par la table de DISQUE...
(Notez que dans ce cas, il y a également un indice qui a couvert ce)
(Une mise à jour LIMITE comme Mysql n'est pas disponible pour PostgresQL)
BTW: Le vrai problème est plus compliqué et que nous parlons d'un système embarqué qui est déjà en place, à distance des modifications de schéma est difficile, mais possible
C'est PostgresQL 7.4 malheureusement.
Le nombre de lignes dont je parle, par exemple, 90000000. La taille de la databse peuvent être de plusieurs dozend gigaoctets.
La base de données elle-même ne contient que 5 tables, l'une est un très gros.
Mais ce n'est pas une mauvaise conception, parce que ces boîtes de fonctionner uniquement avec un type d'entité, ce n'est pas un système ERP ou quelque chose comme ça!
Des idées?
OriginalL'auteur Christian | 2008-09-21
Vous devez vous connecter pour publier un commentaire.
Comment à propos de l'ajout d'une nouvelle table pour stocker cette répliqué valeur (et une clé primaire pour relier chaque enregistrement de la table principale). Il vous suffit d'ajouter un enregistrement pour chaque élément répliqué, et supprimer des enregistrements à supprimer la réplication du pavillon. (Ou peut-être dans l'autre sens, un record pour tous les non répliquée record, selon ce qui est le cas le plus courant).
Qui permettrait également de simplifier le cas où vous souhaitez les mettre tous à 0, que vous pouvez juste tronquer la table (ce qui efface le tableau de taille sur le disque, vous n'avez même pas à vide pour libérer de l'espace)
OriginalL'auteur Dan
Si vous essayez de réinitialiser l'ensemble de la table, et pas seulement quelques lignes, il est généralement plus rapide (sur de très grands ensembles de données -- pas sur les tables régulières) pour simplement
CREATE TABLE bar AS SELECT everything, but, copied, 0 FROM foo
, puis échangez les tables et la chute de l'ancien. Évidemment, vous devez assurer que rien n'est inséré dans la table d'origine tout en vous faites cela. Vous aurez besoin de recréer l'index, trop.Modifier: Une simple amélioration, afin d'éviter le blocage de la table pendant que vous copiez 14 Gigaoctets:
(laissez écrit se produire pendant que vous faites les copier et de les insérer post-factum).
OriginalL'auteur SquareCog
Si vous ne pouvez pas probablement de résoudre le problème de l'utilisation de l'espace (c'est temporaire, juste jusqu'à ce qu'un vide), vous pouvez probablement vraiment accélérer le processus en termes de temps de l'horloge. Le fait que PostgreSQL utilise MVCC signifie que vous devriez être en mesure de le faire sans toutes les questions liées aux nouvelles lignes insérées. Le create table as sélectionnez obtiendrez autour de certains problèmes de performances, mais ne permettra pas l'utilisation continue de la table, et prend autant d'espace. Juste fossé de l'index, et de le reconstruire, puis faire un vide.
OriginalL'auteur Grant Johnson
C'est pseudocode. Vous aurez besoin de 400 mo (pour les entiers) ou 800 MO (pour bigints) fichier temporaire (vous pouvez le compresser avec zlib si c'est un problème). Il aura besoin d'environ 100 scans d'une table pour aspirateurs. Mais il ne va pas gonfler une table de plus de 1% (à plus de 1000000 morts lignes à tout moment). Vous pouvez également le commerce de moins de scans pour plus de table de ballonnement.
OriginalL'auteur Tometzky
Je pense qu'il est préférable de changer votre postgres à la version 8.X. probablement la cause en est la faible version de Postgres. Essayez également de cette requête ci-dessous. J'espère que cela peut vous aider.
OriginalL'auteur norlan V
Je suppose que ce que vous devez faire est de
un. copier les enregistrements de 2000 valeur de clé primaire dans une table temporaire avec la même limite standard, etc.
b. sélectionnez le même 2000 dossiers et effectuer les opérations nécessaires dans le curseur comme il est.
c. En cas de succès, exécutez une seule requête de mise à jour contre les enregistrements dans la table temporaire. Effacer la table temporaire et exécutez l'étape a de nouveau.
d. En cas d'échec, désactivez la table temporaire sans l'exécution de la requête de mise à jour.
Simple, efficace et fiable.
En ce qui concerne,
KT
OriginalL'auteur Kapil