La meilleure approche pour partager des 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 (= shard) 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 est soit des écritures, soit des lectures.
Le cas d'écriture est soit a) la fréquence des écritures surcharge les disques de ce serveur de façon permanente, soit b) il y a trop d'écritures en cours pour que la réplication soit en permanence en retard dans cette hiérarchie de réplication.
Le cas de lecture pour le partitionnement est lorsque la taille des données est si grande que l'ensemble de travail ne tient plus dans la mémoire et que les lectures de données commencent à frapper le disque au lieu d'être servies à partir de la mémoire la plupart du temps.
Ce n'est que lorsque vous devez fragmenter que vous le faites.
Au moment où vous fragmentez, vous payez pour cela de plusieurs façons:
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 contre des données sur le nœud B, ou vous avez une table plus grande qu'un nœud, sur les nœuds A et B et joignez les données de celui-ci avec les 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 qui exprime la fonctionnalité SQL de manière procédurale (par exemple, vous utilisez des instructions SELECT dans des boucles).
Vous subissez beaucoup de latence réseau.
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 partitionné, les requêtes sont résolues soit en exécutant des accès clé-valeur sur un réseau à plusieurs nœuds (avec un peu de chance avec des accès clés par lots et non des recherches de clé individuelles par aller-retour) ou en poussant des parties de la WHERE
clause vers les nœuds où elles peuvent être appliqué (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 autres mécanismes SQL pour l'intégrité des données sont incapables de couvrir plusieurs fragments.
MySQL n'a pas d'API qui autorise les requêtes asynchrones en ordre 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 linéairement avec le nombre de nœuds, à moins que plusieurs nœuds ne puissent être demandés en parallèle et que les résultats soient agrégés au fur et à mesure qu'ils arrivent ("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 du sucer avec un abonnement de saison.
Une fois que vous commencez le partitionnement, la structure des données et la topologie du réseau deviennent visibles en tant que points de performance de votre application. Pour fonctionner raisonnablement bien, votre application doit être consciente de ces éléments, ce qui signifie qu'en réalité, seul le partitionnement au niveau de l'application a du sens.
La question est plus si vous souhaitez effectuer un partitionnement automatique (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 master, tandis que les tables liées abc et def vont à ce master ").
Le partitionnement fonctionnel a l'avantage que, s'il est bien fait, il est la plupart du temps invisible pour la plupart des développeurs, 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 du réseau car le nombre de transferts inter-réseaux est maintenu au minimum.
Le partitionnement fonctionnel présente 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 partitionnement fonctionnel a l'avantage d'être relativement facile à appliquer à une base de code existante avec un certain nombre de modifications qui ne sont pas trop importantes. 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 ne comprends pas du tout votre énoncé de problème.