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.
Partage au niveau de l'application: dbShards est le seul produit que je connaisse qui fasse du «partitionnement sensible aux applications». Il y a quelques bons articles sur le site. Par définition, le partitionnement prenant en charge les applications sera plus efficace. Si une application sait exactement où aller avec une transaction sans avoir à la rechercher ou à être redirigée par un proxy, cela en soi sera plus rapide. Et la vitesse est souvent l'une des principales préoccupations, sinon la seule, lorsque quelqu'un se penche sur le sharding.
Certaines personnes "éclatent" avec un proxy, mais à mes yeux, cela va à l'encontre du but du partage. Vous utilisez simplement un autre serveur pour indiquer à vos transactions où trouver les données ou où les stocker. Grâce au partitionnement prenant en charge les applications, votre application sait par elle-même où aller. Beaucoup plus efficace.
C'est vraiment la même chose que # 2.
la source
Plusieurs nouveaux projets dans cet espace:
github.com/twitter/gizzard/la source
Shard-Query est une solution de partitionnement basée sur OLAP pour MySQL. Il vous permet de définir une combinaison de tables fragmentées et de tables non fragmentées. Les tables non éclatées (comme les tables de recherche) peuvent être jointes librement à des tables partitionnées, et les tables partitionnées peuvent être jointes les unes aux autres tant que les tables sont jointes par la clé de partition (pas de partition croisée ou d'auto-jointures qui traversent les limites de partition). Étant une solution OLAP, Shard-Query a généralement des temps de réponse minimum de 100 ms ou moins, même pour les requêtes simples, donc cela ne fonctionnera pas pour OLTP. Shard-Query est conçu pour analyser des ensembles de Big Data en parallèle.
Des solutions de partitionnement OLTP existent également pour MySQL. Les solutions de source fermée incluent ScaleDB , DBShards . Les solutions OLTP open source incluent JetPants , Cubrid ou Flock / Gizzard (infrastructure Twitter).
la source
Niveau d'application bien sûr.
Meilleure approche que j'ai jamais trouvée dans ce livre
MySQL hautes performances http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064
Brève description: vous pouvez diviser vos données en plusieurs parties et stocker environ 50 parties sur chaque serveur. Cela vous aidera à éviter le deuxième plus gros problème de sharding: le rééquilibrage. Déplacez simplement certains d'entre eux vers le nouveau serveur et tout ira bien :)
Je vous recommande fortement de l'acheter et de lire la partie "mysql scaling".
la source
À partir de 2018, il semble y avoir une solution native MySql à cela. Il y en a en fait au moins 2 - InnoDB Cluster et NDB Cluster (il existe une version commerciale et une version communautaire).
Étant donné que la plupart des utilisateurs de l'édition communautaire MySql sont plus familiers avec le moteur InnoDB, c'est ce qui devrait être exploré en priorité. Il prend en charge la réplication et le partitionnement / partitionnement hors de la boîte et est basé sur MySql Router pour différentes options de routage / d'équilibrage de charge.
La syntaxe pour la création de vos tables devrait changer, par exemple:
(ce n'est que l'un des quatre types de partitionnement )
Une limitation très importante:
la source
PARTITION BY HASH(YEAR...)
seront analysées si vous avez une plage de dates. Beurk.