Base de données Messenger (partie 2): nous partitionnons le «profit»

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
--     CREATE TABLE "_YYYYMMDD"( "" uuid PRIMARY KEY , "" uuid , "" date , "" uuid , "" --    timestamp , "" text ); CREATE TABLE "_YYYYMMDD"( "" date , "" uuid , "" uuid , PRIMARY KEY("", "") ); CREATE TABLE "_YYYYMMDD"( "" date , "" uuid PRIMARY KEY , "" uuid , "BLOB" uuid , "" text ); CREATE TABLE "_YYYYMMDD"( "" date , "" uuid , "" smallint , "" timestamp , "" uuid , PRIMARY KEY("", "", "") ); CREATE INDEX ON "_YYYYMMDD"("", "", "" DESC); --     CREATE TABLE "_YYYYMMDD"( "" date , "" uuid PRIMARY KEY , "" uuid , "" text ); CREATE TABLE "_YYYYMMDD"( "" date , "" uuid , "" uuid , PRIMARY KEY("", "") ); CREATE TABLE "_YYYYMMDD"( "" date , "" uuid PRIMARY KEY , "" date ); 


É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.

Source: https://habr.com/ru/post/fr483170/


All Articles