Optimiser PostgreSQL pour les données transitoires

8

J'ai plusieurs tables avec 100-300 colonnes de types entiers chacune, qui contiennent des données très volatiles. Les jeux de données sont saisis par une ou deux clés primaires et, lors de l'actualisation, l'ensemble de données est supprimé et de nouvelles données sont insérées dans une transaction. La taille de l'ensemble de données est généralement de quelques centaines de lignes, mais peut aller jusqu'à plusieurs milliers de lignes dans les cas extrêmes. L'actualisation a lieu une fois par seconde et les mises à jour des ensembles de données pour différentes clés sont généralement décousues, il est donc impossible de supprimer et de recréer la table.

Comment régler Postgres pour gérer une telle charge? Je peux utiliser la dernière et la meilleure version si cela fait une différence.

Alex Tokarev
la source

Réponses:

7

Selon le nombre d'ensembles de données différents, une option serait de partitionner les tables par ensemble de données.

Lorsqu'un ensemble de données est mis à jour, BEGINune nouvelle transaction, TRUNCATEla table, COPYles nouvelles données qu'il contient et COMMIT. PostgreSQL a une optimisation où l' COPYentrée dans une table qui a été TRUNCATEd dans la même transaction fait beaucoup moins d'E / S si vous utilisez wal_level = minimal(la valeur par défaut).

Si vous ne pouvez pas partitionner et tronquer (par exemple, si vous avez affaire à des dizaines ou des centaines de milliers d'ensembles de données, où il y aurait simplement trop de tables), vous voudrez plutôt activer le vide automatique pour qu'il s'exécute autant que possible. , assurez-vous d'avoir de bons index sur tout ce que vous supprimez et soyez prêt pour des performances quelque peu ordinaires.

Si vous n'avez pas besoin de sécurité en cas de crash - cela ne vous dérange pas que vos tables soient vides après un crash du système - vous pouvez également créer vos tables en tant que UNLOGGED, ce qui vous fera économiser une énorme quantité d'E / S.

Si cela ne vous dérange pas de devoir restaurer l'intégralité de la configuration à partir d'une sauvegarde après un crash système, vous pouvez aller plus loin et également définir fsync=off, ce qui dit à PostgreSQL "ne vous embêtez pas avec la sécurité en cas de crash, j'ai de bonnes sauvegardes et je ne peu m'importe si mes données sont définitivement et totalement irrécupérables après un crash, et je suis heureux de le ré- initdbavant de pouvoir réutiliser ma base de données ".

J'ai écrit un peu plus à ce sujet dans un fil similaire sur Stack Overflow sur l' optimisation de PostgreSQL pour des tests rapides ; qui mentionne l'optimisation du système d'exploitation hôte, séparant WAL sur un autre disque si vous n'utilisez pas de unloggedtables, d'ajustements de pointeur de contrôle, etc.

Il existe également des informations dans les documents Pg pour un chargement rapide des données et des paramètres non durables .

Craig Ringer
la source
Merci pour l'astuce de partition, je n'ai jamais pensé à les utiliser dans ce cas. Quant aux tables non enregistrées - voulez-vous dire qu'elles finissent vides par défaut après un plantage du système? Ça ne fait aucune différence, je suis juste curieux.
Alex Tokarev
1
@AlexTokarev C'est vrai; après que PostgreSQL se soit arrêté de manière incorrecte (postmaster ou un segfaults de backend, les cycles d'alimentation du système soudainement, le backend est SIGKILLédité, etc.) toutes les UNLOGGEDtables peuvent être TRUNCATEd, donc elles sont vides au démarrage. Ils ne sont pas tronqués après un arrêt et un redémarrage propres, mais vous ne devez pas vous fier à leur durabilité.
Craig Ringer
Merci pour l'explication. Je n'ai pas besoin de la sécurité des données pour les tables en question, les données qu'elles contiennent sont transitoires et sont actualisées à partir de la source toutes les secondes. La désactivation de fsync n'est pas une option cependant, car il existe d'autres tables plus traditionnelles dans le même schéma qui doivent être sûres et récupérables. Avoir l' UNLOGGEDoption par table est tout simplement génial.
Alex Tokarev
Je regarde le document de partitionnement et il semble que cela pourrait être une solution (presque) parfaite au problème. Une question cependant: si je vais avoir une table parent pour les tables de schéma et enfant pour contenir les données, je vais interroger les données de la table parent, non? S'il existe une table enfant pour cette plage, la requête la renverra, sinon, elle renverra un ensemble de données vide. Dans ce cas, je peux même supprimer et recréer des tables enfants pour chaque nouveau lot de données. Compte tenu des circonstances, quoi de plus efficace TRUNCATEou de DROP/CREATE TABLEséquence?
Alex Tokarev
@AlexTokarev Je vous recommanderais TRUNCATEpersonnellement. Le taux de désabonnement DDL a ses propres coûts. Étant donné que vous apportez des modifications avec une fréquence aussi élevée, il sera très important de vous assurer que vous augmentez l'agressivité d'Autovacuum pg_catalog.pg_classet d'autres tables système qui pourraient gonfler sous cette charge de travail.
Craig Ringer