MySQL: plusieurs tables ou une table avec plusieurs colonnes?

125

C'est donc plus une question de conception.

J'ai une clé primaire (disons l'ID de l'utilisateur), et j'ai des tonnes d'informations associées à cet utilisateur.

Dois-je avoir plusieurs tableaux divisés en catégories selon les informations, ou devrais-je avoir un seul tableau avec plusieurs colonnes?

La façon dont je le faisais était d'avoir plusieurs tables, disons, une table pour les données d'utilisation des applications, une table pour les informations de profil, une table pour les jetons back-end, etc. pour garder les choses organisées.

Récemment, quelqu'un m'a dit qu'il valait mieux ne pas le faire de cette façon et avoir une table avec beaucoup de colonnes, c'est bien. Le fait est que toutes ces colonnes ont la même clé primaire.

Je suis assez nouveau dans la conception de bases de données, alors quelle approche est la meilleure et quels sont les avantages et les inconvénients?

Quelle est la manière conventionnelle de le faire?

Xavier_Ex
la source
Pour plus de clarté, corrigez-moi si je me trompe, mais je pense que les "tables multiples" peuvent être comprises comme un lien / table associative: en.wikipedia.org/wiki/Associative_entity
cellepo
1
Cette base de données est-elle nécessaire à des fins analytiques ou pour un traitement opérationnel / transactionnel?
Alexander Radev

Réponses:

112

Chaque fois que les informations sont individuelles (chaque utilisateur a un nom et un mot de passe), il est probablement préférable de disposer d'une seule table, car cela réduit le nombre de jointures que la base de données devra effectuer pour récupérer les résultats. Je pense que certaines bases de données ont une limite sur le nombre de colonnes par table, mais je ne m'inquiéterais pas à ce sujet dans les cas normaux, et vous pouvez toujours le diviser plus tard si vous en avez besoin.

Si les données sont un-à-plusieurs (chaque utilisateur a des milliers de lignes d'informations d'utilisation), elles doivent être divisées en tables séparées pour réduire les données en double (les données en double gaspillent de l'espace de stockage, de l'espace de cache et rendent la base de données plus difficile à maintenir ).

Vous trouverez peut-être l'article de Wikipedia sur la normalisation des bases de données intéressant, car il en discute en profondeur les raisons:

La normalisation de la base de données est le processus d'organisation des champs et des tables d'une base de données relationnelle pour minimiser la redondance et la dépendance. La normalisation implique généralement de diviser les grandes tables en tables plus petites (et moins redondantes) et de définir les relations entre elles. L'objectif est d'isoler les données afin que les ajouts, suppressions et modifications d'un champ puissent être effectués dans une seule table, puis propagés dans le reste de la base de données via les relations définies.

La dénormalisation est également une chose à prendre en compte, car il y a des cas où la répétition des données est préférable (car elle réduit la quantité de travail que la base de données doit faire lors de la lecture des données). Je vous recommande vivement de rendre vos données aussi normalisées que possible pour commencer et de ne les dénormaliser que si vous êtes conscient de problèmes de performances dans des requêtes spécifiques.

Brendan Long
la source
Merci pour votre réponse, donc après l'avoir lue, je pense que ce dont je parlais était la situation d'information individuelle, lorsqu'un utilisateur a plusieurs colonnes individuelles.
Xavier_Ex
@Xavier_Ex - Ouais, s'il n'y a qu'une seule colonne par utilisateur, alors une seule énorme table d'utilisateurs sera plus facile à travailler (et beaucoup plus facile à optimiser pour le moteur de base de données).
Brendan Long
Votre message modifié fournit des informations plus utiles! J'ai une nouvelle préoccupation: si certaines des colonnes sont fréquemment mises à jour, dois-je les mettre dans des tableaux séparés? Par exemple, la date de naissance d'un utilisateur ne sera jamais mise à jour, mais le jeton back-end peut être invalidé après une période de temps et nécessitera des mises à jour fréquentes. Serait-il préférable de séparer les tables de cette manière pour améliorer les performances? Je vais maintenant aller lire sur le wiki que vous avez mentionné :)
Xavier_Ex
@Xavier_Ex - Je ne le recommanderais pas. Vous obtenez des performances nettement meilleures lorsque vous pouvez rechercher toutes les données dont vous avez besoin dans une seule table (voir l'article sur la dénormalisation). Les jointures sont coûteuses car (1) elles nécessitent la recherche de données à plusieurs endroits, ce qui peut impliquer des recherches sur un disque rotatif, (2) nécessitent généralement plusieurs index et une sorte de fusion, et (3) elles rendent la planification des requêtes plus difficile, ce qui n'est pas le cas. ne prend que du temps, mais augmente également les chances que l'optimiseur de requêtes obtienne quelque chose de mal (et les requêtes mal optimisées peuvent être très lentes).
Brendan Long
1
Récemment, j'ai été confronté à ce même problème, car les tables MySQL InnoDB ont une limite de longueur relativement petite (~ 8000 octets). Dans ma table de problèmes (données provenant de formulaires d'assurance très longs, plus de 100 colonnes), nous avons plusieurs colonnes varchar, toutes UTF8. Nous avons donc facilement rempli la limite de ~ 8000 octets et obtenu "l'erreur 139 du moteur de stockage" tout le temps. Nous avons donc dû diviser la table. (Nous avons testé avec le nouveau format Barracuda et cela a fonctionné sans division, mais les serveurs de nos clients utilisent toujours MySQL 5.0).
MV.
12

Une grande table est souvent un mauvais choix. Les tables associées sont celles avec lesquelles la base de données relationnelle a été conçue. Si vous indexez correctement et savez comment écrire des requêtes performantes, elles fonctionneront correctement.

Lorsque les tables contiennent trop de colonnes, vous pouvez rencontrer des problèmes avec la taille réelle de la page sur laquelle la base de données stocke les informations. Soit l'enregistrement peut finir par être trop volumineux pour la page, ce qui peut vous empêcher de créer ou de mettre à jour un enregistrement spécifique qui rend les utilisateurs mécontents, soit vous pouvez (au moins dans SQL Server) être autorisé à un débordement pour certains types de données (avec un ensemble de règles que vous devez rechercher si vous faites cela) mais si de nombreux enregistrements dépassent la taille de la page, vous pouvez créer de graves problèmes de performances. Maintenant, comment MYSQL gère les pages et si vous avez un problème lorsque la taille potentielle de la page devient trop grande, vous devrez rechercher dans la documentation de cette base de données.

HLGEM
la source
1
Ah des voix différentes! Ce qui est toujours génial. Merci pour vos informations! Je m'assurerai d'en être conscient lorsque je créerai mes tables ... mais je ne savais pas que je devrais être au courant de ces trucs de bas niveau à l'origine.
Xavier_Ex
4

J'ai un bon exemple. Base de données trop normalisée avec l'ensemble de relations suivant:

people -> rel_p2staff -> staff

et

people -> rel_p2prosp -> prospects

Lorsque les personnes ont des noms et des détails sur les personnes, le personnel n'a que les détails de l'enregistrement du personnel, les prospects n'ont que les détails des prospects, et les tables rel sont des tables de relations avec des clés étrangères de personnes reliant le personnel et les prospects.

Ce type de conception s'applique à l'ensemble de la base de données.

Maintenant, pour interroger cet ensemble de relations, c'est une jointure multi-table à chaque fois, parfois 8 jointures de table et plus. Cela a bien fonctionné jusqu'au milieu de cette année, quand cela a commencé à devenir très lent maintenant que nous avons dépassé les 40000 records de personnes.

L'indexation et tous les fruits à portée de main avaient été utilisés l'année dernière, toutes les requêtes sont optimisées à la perfection. C'est la fin du chemin pour la conception normalisée particulière et la gestion approuvée maintenant une reconstruction de l'application entière qui en dépend ainsi que la restructuration de la base de données, sur une durée de 6 mois. $$$$ Aïe.

La solution sera d'avoir une relation directe pour people -> staffetpeople -> prospect

Vlad
la source
Seriez-vous intéressé de savoir comment s'est déroulée la reconstruction? Avez-vous fini par concevoir quelque chose de similaire à l'héritage de table unique où vous aviez un typeêtre a staffou a prospect?
Coderama
1
Je suis allé avec des personnes en relation directe -> personnel et personnes -> prospect, fonctionne un charme, facile à utiliser, rapide à interroger.
Vlad
4

Je suis tombé sur cela, et en tant que personne qui utilisait beaucoup MySQL, puis qui est passé récemment à Postgres, l'un des grands avantages est que vous pouvez ajouter des objets JSON à un champ dans Postgres.

Donc, si vous êtes dans cette situation, vous ne devez pas nécessairement choisir entre une grande table avec plusieurs colonnes et la diviser, mais vous pouvez fusionner des colonnes en objets JSON pour le réduire, par exemple au lieu que l'adresse soit de 5 colonnes, cela peut simplement être une. Vous pouvez également interroger cet objet.

moinhaque
la source
qu'en est-il des performances lors de l'utilisation d'un objet json lors d'une requête?
dagalti
1
@dagalti les performances sont bonnes pour les applications sur lesquelles je l'ai utilisé. Je n'ai pas fait mon propre benchmarking dessus, mais cela pourrait vous être utile: arangodb.com/2018/02/…
moinhaque
3

posez-vous ces questions si vous mettez tout dans une table, aurez-vous plusieurs lignes pour cet utilisateur? Si vous devez mettre à jour un utilisateur, souhaitez-vous conserver une piste d'audit? L'utilisateur peut-il avoir plus d'une instance d'un élément de données? (comme le numéro de téléphone par exemple) aurez-vous un cas où vous voudrez peut-être ajouter un élément ou un ensemble d'éléments plus tard? si vous répondez oui, vous souhaiterez probablement avoir des tables enfants avec des relations de clé étrangère.

Les avantages des tables parent / enfant sont l'intégrité des données, les performances via les index (oui, vous pouvez le faire sur une table plate également) et l'OMI plus facile à maintenir si vous devez ajouter un champ plus tard, surtout si ce sera un champ obligatoire.

La conception des inconvénients est plus difficile, les requêtes deviennent légèrement plus complexes

Mais, dans de nombreux cas, une grande table plate conviendra, vous devez donc examiner votre situation pour décider.

Brian
la source
Merci de me le rappeler! Donc, dans mon cas, je ne considérais que le cas où chaque utilisateur ne peut pas avoir plus d'une ligne, donc tous les champs d'information sont un à un. De plus, l'utilisateur ne peut pas avoir plus d'une instance du même élément, car je crois que le concept d'un élément ne peut pas exister à plus d'un endroit. Pour la troisième question, oui, je pourrais ajouter d'autres éléments au tableau, mais ils ne briseront pas les exigences que j'ai mentionnées ci-dessus. Je pense que la table parent / enfant est bonne lorsque je veux associer plusieurs lignes à un utilisateur, mais dans ce cas, mon souci est qu'un utilisateur a plusieurs colonnes un-à-une.
Xavier_Ex
même si tous les éléments sont actuellement un à un, cela n'élimine pas le besoin ou le désir d'avoir des tables parent / enfant IMO. Tenir un journal des données modifiées est une utilisation. objets de chargement paresseux en est une autre. bien qu'il y ait des avantages à une structure de table unique, il y a aussi des avantages pour les dispositions parent-enfant (même si j'ai vu des gens aller aux extrêmes avec ces derniers aussi).
Brian
1

J'ai déjà fait une sorte de conception de base de données. pour moi, cela dépend de la difficulté du système avec la gestion de la base de données; oui, il est vrai d'avoir des données uniques en un seul endroit, mais il est vraiment difficile de faire des requêtes avec une base de données trop normalisée avec beaucoup d'enregistrements. Combinez simplement les deux schémas; utilisez une table énorme si vous pensez que vous aurez des enregistrements massifs difficiles à maintenir, tout comme Facebook, Gmail, etc. et utiliser une table différente pour un jeu d'enregistrements pour un système simple ... eh bien c'est juste mon avis .. j'espère que cela pourrait aider .. faites-le ... vous pouvez le faire ... :)

christophe
la source
1
"utilisez une table énorme si vous allez avoir un nombre énorme d'enregistrements." Mais Facebook, Google ne stocke pas les données utilisateur dans une seule table, ils les ont séparés autant de tables.
Yami Odymel du
0

La manière conventionnelle de le faire serait d'utiliser des tables différentes comme dans un schéma en étoile ou un schéma en flocon de neige. Cependant, je baserais cette stratégie sur deux volets. Je crois en la théorie selon laquelle les données ne devraient exister qu'à un seul endroit, car le schéma que j'ai mentionné fonctionnerait bien. Cependant, je pense également que pour les moteurs de reporting et les suites BI, une approche en colonnes serait extrêmement bénéfique car elle répond davantage aux besoins de reporting. Les approches en colonnes comme celles avec infobright.org ont d'énormes gains de performances et de compression qui rendent l'utilisation des deux approches extrêmement utile. De nombreuses entreprises commencent à se rendre compte qu'une seule architecture de base de données dans l'organisation ne répond pas à l'ensemble de leurs besoins. De nombreuses entreprises mettent en œuvre à la fois le concept d'avoir plus d'une architecture de base de données.

Craig Trombly
la source
Merci pour l'information, mais désolé je ne comprends pas très bien votre réponse ... Je vais faire une recherche sur les deux schémas que vous avez mentionnés en premier ...
Xavier_Ex
-4

Je pense qu'avoir un seul tableau est plus efficace, mais vous devez vous assurer que le tableau est organisé de manière à montrer la relation, la tendance ainsi que la différence entre les variables d'une même ligne. par exemple, si le tableau montre l'âge et les notes des élèves, vous devez le disposer de manière à ce que le meilleur score soit bien différencié avec le score le plus bas et que la différence d'âge des élèves soit égale.

user8081853
la source