Il y a 2 parties à ma question.
- Existe-t-il un moyen de spécifier la taille initiale d'une base de données dans PostgreSQL?
- 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.
- 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);
- 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.