Fractionnement des tables dans MySQL. Bonnes pratiques?

14

J'ai commencé à travailler sur un projet existant et le développeur précédent avait divisé une table en 10 tables distinctes avec des schémas identiques mais des données différentes.

Les tableaux ressemblent à ceci:

[tableName_0]
[tableName_1]
[tableName_2]
[tableName_3]
[tableName_4]
[tableName_5]
[tableName_6]
[tableName_7]
[tableName_8]
[tableName_9]

La clé primaire est un idchamp entier . L'application utilise un algorithme de hachage ( idmod 10) pour savoir à quelle table accéder lors des recherches. Par exemple id= 10 résulterait en [tableName_0].

Ensemble, les tableaux ont probablement 100 000 lignes et le taux de croissance est relativement faible.

Donc, ma question est de savoir si c'est une solution viable ou même si c'est une bonne pratique dans n'importe quelle situation. Ma théorie est de pousser à les combiner car cela facilitera les choses en ce qui concerne UNIONs, etc. L'inconvénient principal est de changer tout le code d'application et de savoir s'il en vaut la peine à long terme.

Pamplemousse rose
la source

Réponses:

16

Je pense que tout le monde complique trop cela. Le point clé ici est:

Ensemble, les tableaux ont probablement 100 000 lignes et le taux de croissance est relativement faible.

C'est un morceau de gâteau pour tout SGBDR à gérer. Allez avec une table, indexez-la correctement et considérez-la comme un problème résolu.

Vous n'avez pas besoin de considérer le partitionnement, qu'il soit "fait maison" ou autre, jusqu'à ce que vous commenciez à gérer des volumes de données extrêmement importants - pensez à des milliards de lignes et plus.

Nick Chammas
la source
3

Vous pouvez utiliser des tables de fusion, mais elles sont plus anciennes que les versions 4.x. Étant donné que votre application est partitionnée manuellement car c'est soit a) vous exécutez une version vraiment ancienne, soit b) le développeur d'origine n'était pas au courant des partitions de table.

En bref, si vous utilisez 5.1+, vous pouvez laisser mysql faire ce partitionnement pour vous. Voir http://dev.mysql.com/doc/refman/5.1/en/partitioning.html Si vous utilisez 5.5, vous devriez vérifier ces documents spécifiques car vous trouverez des différences.

Le partitionnement présente de nombreux avantages. Cependant, cela dépend vraiment de l'ensemble de données à portée de main, des modèles d'accès et de la façon dont il doit être indexé. Aussi, gardez à l'esprit que mes commentaires suivants sont dans le contexte du partitionnement mysql 5+, PAS des tables de fusion mysql plus anciennes; bien qu'ils soient parfois discutés en termes de partitions.

Quelques exemples:

  • Compartimentage direct (ou hachage) basé sur la clé de recherche fréquemment utilisée. Si vous recherchez presque toujours une clé primaire ou une autre clé unique, alors mysql peut réduire l'espace de recherche en fonction du nombre de partitions dont vous disposez. Notez cependant que cela peut être préjudiciable si vous partitionnez avec une clé, puis effectuez fréquemment une recherche avec une autre clé. Si vous recherchez par une clé les données ne sont pas partitionnées par alors il doit faire PLUS de recherches sur les recherches (une pour chaque partition, b / c franchement, il ne sait pas où se trouvent les données)
  • Considérez les situations où vous disposez d'un ensemble temporel d'enregistrements qui augmente selon la date et que vous élaguez périodiquement le mois précédent. Si vous partitionnez par date, vous pouvez simplement supprimer une partition aussi rapide que la suppression d'une table, quelle que soit sa taille. Si vous deviez élaguer un tel tableau par date, vous devriez émettre une ou plusieurs requêtes DELETE où chaque ligne individuelle est supprimée. L'inconvénient est que mysql ne crée pas automatiquement de nouvelles partitions une fois que vous avez atteint la date maximale que vous avez prise en compte dans ce scénario; vous avez besoin de scripts de maintenance supplémentaires construits sur votre partie pour ajouter des partitions au besoin.
  • Si vous utilisez myisam, les vérifications et les récupérations sont beaucoup plus rapides. Considérez une table 100G myisam. Si vous souhaitez récupérer une table en panne, vous aurez besoin d'au moins 100 Go d'espace disque disponible au moins. S'il a été partitionné en 10 morceaux différents de taille égale, vous n'avez besoin que de 10 Go d'espace (et moins de mémoire key_sort_buffer pour une récupération rapide); mais aurait besoin de faire une itération pour chaque partition.

Donc en résumé, l'approche générale du partitionnement des tables peut offrir de nombreux avantages. Cependant, ce n'est pas une solution miracle à appliquer à l'aveuglette sans tenir compte des modèles d'accès et de la façon exacte dont vous partitionnez.

Je pourrais imaginer des situations où le partitionnement souhaité est très spécifique à l'application et serait mieux adapté pour que cette logique se trouve dans la couche application. Cependant, étant donné votre description du module droit 10, cela ne semble pas être le cas.

ÉDITER

En écrivant ma description, j'ai oublié que vous avez déclaré que votre table est de 100 000 lignes. Sans le schéma complet de votre table et sa longueur moyenne de ligne, il est difficile de dire avec certitude, mais en général, cela semble de taille moyenne même pour du matériel modeste. Dans le même temps, si cela ne cause pas de problèmes tels qu'ils sont actuellement ou dans un avenir prévisible, ne perdez pas de temps et n'introduisez pas de risque en le modifiant.

atxdba
la source
3

Ce que le développeur précédent a fait pour vous, c'est de construire sa propre implémentation de partition par hachage. MySQL prend littéralement cela en charge de manière native depuis MySQL 5.1:

http://dev.mysql.com/doc/refman/5.1/en/partitioning-hash.html

Je ne peux pas penser à une bonne raison alors implémentez votre propre partition par hachage plutôt que de compter sur la version native [1]. Effectuer des changements de schéma sera un cauchemar.

Je recommande également rarement la partition par hachage (l'implémentation native). Je pense qu'il serait utile que vous puissiez l'utiliser pour rechercher en parallèle chacune des partitions à la fois (ce que MySQL ne fera pas). Si vous devez rechercher sur plusieurs partitions, le schéma que vous avez décrit sera souvent beaucoup plus lent.

[1] Cependant, pour certains des autres types de partitionnement, il peut être judicieux de rouler votre propre partitionnement. MySQL vous oblige à intégrer votre clé de partition à votre clé primaire et à tous les index uniques.

Morgan Tocker
la source
2

En réponse à la question:

est de savoir si c'est une solution viable

À mon humble avis, cela semble comme des frais généraux inutiles. Vous pouvez simplement indexer et partitionner une seule table correctement, sauf s'il existe d'autres informations non révélées dans la description.

En réponse à la question:

... si c'est une bonne pratique dans n'importe quelle situation

À mon humble avis, le partage vertical peut avoir un sens selon le contexte. Quand je vois cela, c'est généralement sous une forme de journal. Imaginons que nous l'utilisions pour les journaux du serveur Web et que nous voulons partitionner par mois. Au lieu de modifier une table existante en place tous les jours, nous pourrions créer une nouvelle table tous les jours et enregistrer des lignes dans cette table.

Par exemple, faire semblant qu'une table de journalisation Web peut prendre la forme:

datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
uri VARCHAR(1024),
host VARCHAR(255),
user_agent VARCHAR(255),
etc...

Votre solution crée des tables selon les besoins dans la base de données du blog:

weblogs.20120301
weblogs.20120302
weblogs.20120303

etc.

De cette façon, les données restent maintenables et consultables. L'extraction devient un processus périodique normal. Les opérations en continu ne sont pas bloquées par les opérations sur des données plus anciennes.

Dans le scénario que vous avez présenté, vous êtes de toute façon enfermé dans une structure, alors pourquoi ne pas utiliser une seule table optimisée à cet effet? Le stockage des lignes basé sur un algorithme semble sommaire et sujet aux erreurs.

randomx
la source
0

Si une requête cible d'énormes données, la répartition des données par conditions de requête entraînerait une amélioration notable des performances. Mais une telle division, comme vous l'avez vu, soulève certains problèmes de programmation.

La question est donc la suivante: ce partage vaut-il pour les performances ou nuit-il aux performances?

Si vous avez une transaction qui doit verrouiller plusieurs lignes sur plusieurs tables et qu'il y a des problèmes (par exemple, un blocage ou un délai d'expiration de transaction), vous pouvez les combiner en une seule table et réécrire le SQL pour réparer les problèmes.

Quand je réfléchis à la séparation de la table, je considérais le compromis entre l'amélioration des performances et la complexité de la programmation.

Dans votre situation, la modification du code existant peut être une solution à long terme pour faciliter la maintenance du code. Je suggère un essai de méta-programmation. Par exemple, utiliser StringTemplate pour générer dynamiquement du SQL. J'aime générer du SQL à partir du moteur de méta-programmation si la modification du code existant est trop difficile.

Mike Lue
la source
0

Lorsque vous devez stocker des fichiers dans un tableau, utiliser cette métodologie permet d'exporter, de réparer et de restaurer.

J'ai des tables avec> 30 Go partitionnées en 10 tables. Ces tableaux n'ont que ID - BLOB et pour moi, c'est facile à conserver. Et j'utilise MyISAM pour enregistrer le tampon INNODB.

Marcelo Bus
la source