Mysql
 sql >> Base de données >  >> RDS >> Mysql

Approches de partitionnement MySQL ?

La meilleure approche pour partitionner les tables MySQL est de ne pas le faire à moins qu'il ne soit totalement inévitable de le faire.

Lorsque vous écrivez une application, vous souhaitez généralement le faire d'une manière qui maximise la vitesse, la vitesse du développeur. Vous optimisez la latence (temps jusqu'à ce que la réponse soit prête) ou le débit (nombre de réponses par unité de temps) uniquement lorsque cela est nécessaire.

Vous partitionnez puis attribuez des partitions à différents hôtes (=partition) uniquement lorsque la somme de toutes ces partitions ne tient plus sur une seule instance de serveur de base de données - la raison en étant soit des écritures, soit des lectures.

Le cas d'écriture est soit a) la fréquence des écritures surcharge en permanence les disques de ce serveur, soit b) il y a trop d'écritures en cours, de sorte que la réplication est en permanence à la traîne dans cette hiérarchie de réplication.

Le cas de lecture pour le partitionnement se produit lorsque la taille des données est si grande que l'ensemble de travail de celles-ci ne tient plus dans la mémoire et que les lectures de données commencent à atteindre le disque au lieu d'être servies à partir de la mémoire la plupart du temps.

Uniquement lorsque vous avez pour shard vous le faites.

Au moment où vous partagez, vous payez pour cela de plusieurs manières :

Une grande partie de votre SQL n'est plus déclarative.

Normalement, en SQL, vous indiquez à la base de données quelles données vous voulez et laissez à l'optimiseur le soin de transformer cette spécification en un programme d'accès aux données. C'est une bonne chose, car c'est flexible, et parce que l'écriture de ces programmes d'accès aux données est un travail ennuyeux qui nuit à la vitesse.

Avec un environnement partitionné, vous joignez probablement une table sur le nœud A aux données du nœud B, ou vous avez une table plus grande qu'un nœud, sur les nœuds A et B et vous joignez les données de celle-ci aux données qui se trouvent sur les nœuds B et C. Vous commencez à écrire manuellement des résolutions de jointure basées sur le hachage côté application afin de résoudre cela (ou vous réinventez le cluster MySQL), ce qui signifie que vous vous retrouvez avec beaucoup de SQL qui n'est plus déclaratif, mais exprime la fonctionnalité SQL de manière procédurale (par exemple, vous utilisez des instructions SELECT dans des boucles).

Vous subissez une latence réseau importante.

Normalement, une requête SQL peut être résolue localement et l'optimiseur connaît les coûts associés aux accès au disque local et résout la requête d'une manière qui minimise les coûts pour cela.

Dans un environnement fragmenté, les requêtes sont résolues soit en exécutant des accès clé-valeur sur un réseau vers plusieurs nœuds (espérons-le avec des accès clés par lots et non des recherches de clés individuelles par aller-retour) ou en poussant des parties de WHERE clause vers les nœuds où ils peuvent être appliqués (c'est ce qu'on appelle 'condition pushdown'), ou les deux.

Mais même dans le meilleur des cas, cela implique beaucoup plus d'allers-retours réseau qu'une situation locale, et c'est plus compliqué. D'autant plus que l'optimiseur MySQL ne sait rien du tout sur la latence du réseau (Ok, le cluster MySQL s'améliore lentement, mais pour MySQL vanille en dehors du cluster, c'est toujours vrai).

Vous perdez beaucoup de puissance expressive de SQL.

Ok, c'est probablement moins important, mais les contraintes de clé étrangère et d'autres mécanismes SQL pour l'intégrité des données sont incapables de s'étendre sur plusieurs partitions.

MySQL n'a pas d'API qui autorise les requêtes asynchrones en état de marche.

Lorsque des données du même type résident sur plusieurs nœuds (par exemple, des données utilisateur sur les nœuds A, B et C), les requêtes horizontales doivent souvent être résolues sur tous ces nœuds ("Rechercher tous les comptes d'utilisateurs qui n'ont pas été connectés depuis 90 jours ou plus"). Le temps d'accès aux données augmente de manière linéaire avec le nombre de nœuds, à moins que plusieurs nœuds puissent être interrogés en parallèle et que les résultats soient agrégés au fur et à mesure ("Map-Reduce").

La condition préalable pour cela est une API de communication asynchrone, qui n'existe pas pour MySQL en bon état de fonctionnement. L'alternative est beaucoup de bifurcations et de connexions dans les processus enfants, qui visitent le monde de sucer sur un abonnement de saison.

Une fois que vous avez commencé le partitionnement, la structure des données et la topologie du réseau deviennent visibles en tant que points de performance pour votre application. Pour fonctionner raisonnablement bien, votre application doit être consciente de ces éléments, ce qui signifie que seul le partitionnement au niveau de l'application a du sens.

La question est plutôt de savoir si vous souhaitez auto-sharder (déterminer quelle ligne va dans quel nœud en hachant les clés primaires par exemple) ou si vous souhaitez fractionner fonctionnellement de manière manuelle ("Les tables liées à la user story xyz vont à ceci maître, tandis que les tables liées à abc et def vont à ce maître").

Le partitionnement fonctionnel a l'avantage que, s'il est bien fait, il est invisible pour la plupart des développeurs la plupart du temps, car toutes les tables liées à leur user story seront disponibles localement. Cela leur permet de continuer à bénéficier du SQL déclaratif aussi longtemps que possible, et entraînera également moins de latence réseau car le nombre de transferts entre réseaux est maintenu au minimum.

Le partitionnement fonctionnel a l'inconvénient de ne pas permettre à une seule table d'être plus grande qu'une instance, et il nécessite l'attention manuelle d'un concepteur.

Le partage fonctionnel a l'avantage d'être relativement facile à appliquer à une base de code existante avec un nombre de modifications qui n'est pas trop important. http://Booking.com l'a fait plusieurs fois au cours des dernières années et cela a bien fonctionné pour eux.

Cela dit, en regardant votre question, je pense que vous posez les mauvaises questions, ou je comprends complètement mal votre énoncé de problème.