Taille initiale de la base de données PostgreSQL


12

Il y a 2 parties à ma question.

  1. Existe-t-il un moyen de spécifier la taille initiale d'une base de données dans PostgreSQL?
  2. Si ce n'est pas le cas, comment gérez-vous la fragmentation lorsque la base de données se développe au fil du temps?

J'ai récemment migré de MSSQL vers Postgres, et l'une des choses que nous avons faites dans le monde MSSQL lors de la création d'une base de données a été de spécifier la taille initiale de la base de données et du journal des transactions. Cela réduit la fragmentation et augmente les performances, surtout si la taille "normale" de la base de données est connue à l'avance.

Les performances de ma base de données diminuent à mesure que la taille augmente. Par exemple, la charge de travail que je subis prend normalement 10 minutes. À mesure que la base de données se développe, ce temps augmente. Faire un VIDE, VACUUM FULL et VACUUM FULL ANALYZE ne semble pas résoudre le problème. Ce qui résout le problème de performances, c'est d'arrêter la base de données, de fragmenter le lecteur puis de faire un ANALYSE PLEIN SOUS VIDE ramène les performances de mon test aux 10 minutes d'origine. Cela m'amène à soupçonner que la fragmentation est ce qui me fait mal.

Je n'ai pas pu trouver de référence à la réservation d'espace table / base de données dans Postgres. Soit j'utilise la mauvaise terminologie et ne trouve donc rien, soit il existe un autre moyen d'atténuer la fragmentation du système de fichiers dans Postgres.

Des pointeurs?

La solution

Les réponses fournies ont permis de confirmer ce que j'avais commencé à soupçonner. PostgreSQL stocke la base de données sur plusieurs fichiers et c'est ce qui permet à la base de données de croître sans se soucier de la fragmentation. Le comportement par défaut consiste à compresser ces fichiers à ras bord avec des données de table, ce qui est bon pour les tables qui changent rarement mais est mauvais pour les tables fréquemment mises à jour.

PostgreSQL utilise MVCC pour fournir un accès simultané aux données de table. Dans ce schéma, chaque mise à jour crée une nouvelle version de la ligne qui a été mise à jour (cela peut être via l'horodatage ou le numéro de version, qui sait?). Les anciennes données ne sont pas immédiatement supprimées, mais marquées pour suppression. La suppression effective se produit lorsqu'une opération VACUUM est effectuée.

Quel est le lien avec le facteur de remplissage? Le facteur de remplissage par défaut de la table de 100 emballe complètement les pages du tableau, ce qui signifie à son tour qu'il n'y a pas d'espace dans la page du tableau pour contenir les lignes mises à jour, c'est-à-dire que les lignes mises à jour seront placées dans une page de tableau différente de la ligne d'origine. C'est mauvais pour les performances, comme mon expérience le montre. Comme mes tableaux récapitulatifs sont mis à jour très fréquemment (jusqu'à 1500 lignes / sec), j'ai choisi de définir un facteur de remplissage de 20, c'est-à-dire que 20% du tableau sera pour les données de ligne insérées et 80% pour les données de mise à jour. Bien que cela puisse sembler excessif, la grande quantité d'espace réservé pour les lignes mises à jour signifie que les lignes mises à jour restent dans la même page que l'original et qu'il y a une page de tableau qui n'est pas pleine au moment où le démon autovacuum s'exécute pour supprimer les lignes obsolètes.

Pour "réparer" ma base de données, j'ai fait ce qui suit.

  1. Définissez le facteur de remplissage de mes tableaux récapitulatifs sur 20. Vous pouvez le faire au moment de la création en passant un paramètre à CREATE TABLE , ou après coup via ALTER TABLE. J'ai émis la commande plpgsql suivante:ALTER TABLE "my_summary_table" SET (fillfactor = 20);
  2. Un VACUUM FULL a été émis, car cela écrit une version complètement nouvelle du fichier de table et donc implicitement écrit un nouveau fichier de table avec le nouveau facteur de remplissage .

En réexécutant mes tests, je ne constate aucune dégradation des performances même lorsque la base de données est aussi volumineuse que je le souhaite avec plusieurs millions de lignes.

TL; DR - La fragmentation des fichiers n'était pas la cause, c'était la fragmentation de l'espace table. Ceci est atténué en ajustant le facteur de remplissage de la table pour l'adapter à votre cas d'utilisation particulier.


Je doute que ce soit l'opération de redimensionnement de fichier. Je suppose que le maintien des index est ce qui ralentit les insertions. Il y a une discussion en cours sur la liste de diffusion PG à ce sujet (mais sans solution): postgresql.1045698.n5.nabble.com/…
a_horse_with_no_name

Réponses:


4
  1. La seule chose proche de cela est lorsque vous compilez le serveur avec le commutateur --with-segsize, cela pourrait aider si votre table prend plus d'espace qu'un concert et que votre système de fichiers peut gérer un seul fichier sur un concert. Si vous insérez 20 concerts, il devra créer 20 fichiers si vous n'utilisez pas ce commutateur. Si votre système de fichiers peut gérer un fichier sur un concert, vous pouvez simplement le définir sur une grande valeur, vous verrez probablement un avantage, dans le pire des cas un petit avantage.

  2. Jetez un œil à CLUSTER http://www.postgresql.org/docs/9.1/static/sql-cluster.html et FILLFACTOR http://www.postgresql.org/docs/9.1/static/sql-createtable.html , http://www.postgresql.org/docs/9.1/static/sql-createindex.html

Notez que FILLFACTOR peut être appliqué à la fois aux tables et aux index.


5

Il y a une autre chose en jeu qui n'a pas encore entré vos équations: la mise à jour HOT . Réponses associées:

Un réglage FILLFACTORaussi bas que 20 cela semble excessif. Il gonfle la table jusqu'à cinq fois sa taille. Si les mises à jour HOT fonctionnent, vous ne devriez pas avoir à descendre aussi bas - normalement .

Il existe des exceptions: les mises à jour HOT peuvent uniquement réutiliser des tuples morts à partir de transactions précédentes , et non à partir de transactions identiques ou simultanées . Par conséquent, un chargement simultané lourd ou des transactions longues mettant à jour de manière répétée les mêmes lignes peuvent justifier un paramètre aussi bas (ou même inférieur).

Si vous avez de grosses mises à jour et que vous changez de grandes parties de la table en même temps, vous souhaiterez peut-être les diviser en quelques morceaux, idéalement en ne changeant que le nombre de lignes à la fois en fonction de la taille locale sur la page de données. Mais c'est difficile à estimer et à réglementer.

Notez que les mises à jour HOT ne fonctionnent que lorsque les colonnes modifiées ne sont impliquées dans aucun index (ni comme données ni comme condition dans un index partiel). Vous bloquez peut-être les mises à jour HOT avec des index sur les colonnes mises à jour. Si ceux-ci sont consommables, vous pourriez obtenir de meilleures performances globales sans eux.

Enfin, vous pouvez définir des paramètres de vide automatique par table . Vous pouvez cibler des tableaux fortement mis à jour avec des paramètres agressifs permettant un emballage des lignes un peu plus serré que seulement FILLFACTOR 20.


1
Choses intéressantes, je vais les lire et essayer de mieux comprendre ce que les mises à jour HOT signifient pour mon système.
CadentOrange

4

Si votre problème est la fragmentation des fichiers, alors non, il n'y en a pas. Dans Postgres, chaque table obtient son propre fichier, ou un ensemble de fichiers si elle utilise TOAST, dans le système de fichiers. Cela diffère, par exemple, d'Oracle (ou apparemment MS-SQL) où vous créez des fichiers d'espace de table prédéfinis dans lesquels déposer vos tables - même si là-bas, vous pourriez avoir des problèmes de fragmentation du système de fichiers si les fichiers d'espace de table sont étendus ou si le système de fichiers est mal fragmenté pour commencer.

Quant à votre deuxième question ... Je n'ai aucune idée de comment traiter correctement la fragmentation du système de fichiers car MS-Windows est le seul système d'exploitation où j'ai rencontré des problèmes de fragmentation et je n'exécute pas MS-Windows plus qu'absolument. besoin d'être de nos jours. Peut-être que le fait de placer les fichiers de la base de données sur leurs propres disques pourrait atténuer cela dans une certaine mesure.


Gardez à l'esprit que vous avez une fragmentation de la base de données PostgreSQL interne et une fragmentation du système de fichiers externe. Interne, je pense, peut être atténué avec VACUUM et en utilisant CLUSTERS et FILLFACTOR. Le système de fichiers peut être géré en exécutant une défragmentation pour le système de fichiers donné. Et les systèmes de fichiers Linux / Unix peuvent parfois être fragmentés en fonction de la charge de travail et du type de système de fichiers.
Kuberchaun

La fragmentation du système de fichiers n'est pas vraiment un gros problème avec NTFS de nos jours.
a_horse_with_no_name

1
Je pensais que NTFS était connu pour ça? Ma machine de poste de travail est assez bien fragmentée, la seule chose qui la garde sous contrôle est une défragmentation planifiée que Windows7 exécute quotidiennement.
Kuberchaun
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.