Nous avons réussi à concevoir la structure de notre base de données PostgreSQL pour stocker la correspondance, un an s'est écoulé, les utilisateurs la remplissent activement, elle a maintenant des
millions d'enregistrements , et ... quelque chose a commencé à ralentir.

Le fait est
qu'avec la croissance du volume de la table, la «profondeur» des indices croît également - quoique logarithmiquement. Mais au fil du temps, cela oblige le serveur à
traiter de nombreuses pages de données pour effectuer les mêmes tâches de lecture / écriture qu'au début.
C'est là que le
partitionnement vient à la rescousse.
Je note qu'il ne s'agira pas de partage, c'est-à-dire de la distribution de données entre différentes bases de données ou serveurs. Car, même en divisant les données sur
plusieurs serveurs, vous ne pouvez pas vous débarrasser du problème de «gonflement» des index au fil du temps. Il est clair que si vous pouvez vous permettre de mettre en service un nouveau serveur chaque jour, vos problèmes ne se situeront plus dans le plan d'une base de données spécifique.
Nous ne considérerons pas des scripts spécifiques pour implémenter le partitionnement «dans le matériel», mais l'approche elle-même - quoi et comment «couper en tranches», et à quoi conduit un tel désir.
Concept
Encore une fois, nous définissons notre objectif: nous voulons nous assurer qu'aujourd'hui, demain et après un an, le nombre de données PostgreSQL lues lors d'une opération de lecture / écriture reste à peu près le même.
Pour toute
donnée chronologiquement accumulée (messages, documents, logs, archives, ...), le choix naturel comme clé de partition est la
date / heure de l'événement . Dans notre cas, un tel événement est le
moment où le message a été envoyé .
Notez que les utilisateurs
ne travaillent presque toujours
qu'avec les "dernières" données - ils lisent les derniers messages, analysent les derniers journaux ... Non, bien sûr, ils peuvent remonter dans le temps, ne le font que très rarement.
De ces limites, il devient évident que les
sections «quotidiennes» seront la meilleure solution pour les messages - après tout, notre utilisateur lira presque toujours ce qui lui est arrivé «aujourd'hui» ou «hier».
Si nous écrivons et lisons presque seulement une section pendant la journée, cela nous donne
une utilisation encore
plus efficace de la mémoire et du disque - puisque tous les indices de section s'intègrent facilement dans la RAM, contrairement aux sections "grandes et en gras" de la table entière.
étape par étape
En général, tout ce qui précède ressemble à un bénéfice solide. Et c'est réalisable, mais pour cela, nous devrons faire des efforts - parce que la
décision de partitionner l'une des entités conduit à la nécessité de «couper» et de lui associer .
Message, ses propriétés et projections
Puisque nous avons décidé de couper les messages par dates, il est également raisonnable de diviser les entités-propriétés (fichiers joints, listes de diffusion), ainsi que
par la date du message , selon elles.
Étant donné que l'une de nos tâches typiques consiste simplement à afficher les registres de messages (non lus, entrants, tous), il est également logique de les «attirer» dans le partitionnement par date de message.

Ajoutez la clé de partition (date du message) à toutes les tables: destinataires, fichier, registres. Vous ne pouvez pas ajouter au message lui-même, mais utilisez le DateTime existant.
Thèmes
Comme le sujet est un en plusieurs messages, il ne sera pas possible de le «couper» dans le même modèle, il faut compter sur autre chose. Dans notre cas, la
date du premier message en correspondance est idéale - c'est-à-dire le moment de la création du sujet lui-même.

Ajoutez la clé de partition (date du sujet) à toutes les tables: sujet, participant.
Mais maintenant, nous avons deux problèmes à la fois:
- dans quelle section rechercher des articles sur le sujet?
- dans quelle section rechercher un sujet dans un message?
Vous pouvez bien sûr continuer à chercher dans toutes les sections, mais ce sera très triste et annulera tous nos gains. Par conséquent, afin de savoir exactement où chercher, nous allons créer des liens / pointeurs logiques vers les sections:
- dans le message, ajoutez un champ avec la date du sujet
- ajouter au sujet un ensemble de dates de message pour cette correspondance (vous pouvez utiliser un tableau séparé ou vous pouvez utiliser un tableau de dates)

Puisqu'il y aura peu de modifications à la liste des dates de message pour chaque correspondance individuelle (après tout, presque tous les messages tombent en 1-2 jours adjacents), je m'attarderai sur cette option.
Total, la structure de notre base a pris la forme suivante, en tenant compte du partitionnement:
Tables: RU, si vous n'aimez pas le cyrillique, il vaut mieux ne pas regarder les noms des tables / champs Économisez un joli sou
Eh bien, si nous n'utilisons pas l'
option de partitionnement classique basée sur la distribution des valeurs de champ (via les déclencheurs et l'héritage ou PARTITION BY), mais «manuellement» au niveau de l'application, nous pouvons voir que la valeur de la clé de partitionnement est déjà stockée dans le nom de la table elle-même.
Par conséquent, si vous êtes tellement
préoccupé par la quantité de données stockées , vous pouvez vous débarrasser de ces champs "supplémentaires" et vous référer à des tableaux spécifiques. Certes, tous les échantillons de plusieurs sections dans ce cas devront être soumis à la candidature.