2010-03-18 3 views
5

Je prévois de construire un projet de base de données.Tableau avec beaucoup d'attributs

L'une des tables possède de nombreux attributs.

Ma question est: Quoi de mieux, de diviser la classe en 2 tables distinctes ou les mettre tous dans une table. ci-dessous un exemple

create table User { id, name, surname,... show_name, show_photos, ...) 

ou

create table User { id, name, surname,...) 
create table UserPrivacy {usr_id, show_name, show_photos, ...) 

La performance je suppose est similaire en raison de je peux utiliser l'index.

+0

Qu'entendez-vous par "Mieux"? Plus rapide? Moins cher? Plus simple? Plus de mémoire utilisée? Plus d'E/S utilisées? Taux plus élevé facturable? Plus de sécurité d'emploi? –

+0

Je pense, l'heure est à peu près la même, la mémoire aussi, mais les E/S en utilisant - cela vaut la peine d'examiner – Robert

Répondre

-2

Je suggère quelque chose de différent. Il semble probable qu'à l'avenir, on vous demandera «encore un autre attribut» à gérer. Plutôt que d'ajouter une colonne, vous pouvez simplement ajouter une ligne à une table d'attributs:

TABLE Attribute 
(
    ID 
    Name 
) 
TABLE User 
(
    ID 
    ... 
) 
TABLE UserAttributes 
(
    UserID FK Users.ID 
    Attribute FK Attributes.ID 
    Value... 
) 

Bons commentaires de tous. J'aurais dû être plus clair dans ma réponse.

Nous faisons cela un peu pour gérer les cas spéciaux où les clients nous demandent d'adapter notre site pour eux d'une manière ou d'une autre. Nous ne «pivotons» jamais les NVP dans les colonnes d'une requête - nous demandons toujours «est-ce que je devrais le faire ici? en recherchant un attribut spécifique répertorié pour un client. Si c'est là, c'est un 'vrai'. Donc, plutôt que d'avoir une tonne de colonnes booléennes, dont la plupart seraient fausses ou NULES pour la plupart des clients, ET la tendance de ces fonctionnalités à augmenter en nombre, cela fonctionne bien pour nous.

+5

Ceci est une suggestion qui ne sera pas bien à l'échelle. Les tables EAV sont connues pour être extrêmement médiocres et, dans la plupart des cas, doivent être évitées. – HLGEM

+1

Je combats les EAV comme je suis St. George, ils sont un dragon. Mais N8 est correct, si la seule requête que vous voulez exécuter est la sienne, "Dois-je faire ceci pour cet utilisateur, vous allez bien, c'est un accès d'index unique pour une ligne ... N8 devrait jamais essayer de trouver tous le client qui a deux ou plusieurs privilèges, il peut aller faire le dîner –

0

Vous devez envisager de fractionner la table si tous les attributs de confidentialité sont nullables et auront très probablement des valeurs de NULL.

Cela vous aidera à réduire la taille de la table principale.

Si les attributs de confidentialité sont généralement remplis, il est inutile de diviser la table, car il faudra JOIN s supplémentaire pour récupérer les données.

2

Je dirais que les 2 tables séparées, surtout si vous utilisez ORM. Dans la plupart des cas, il est préférable que chaque table corresponde à un objet particulier et que son ou ses «attributs» soient des éléments nécessaires pour décrire cet objet.

Vous n'avez pas besoin de 'show_photos' pour décrire un utilisateur, mais vous en avez besoin pour décrire UserPrivacy.

+0

show_photos et show_name sont des attributs de l'utilisateur Avec ORM, généralement tous les attributs seront chargés, que vous les utilisiez ou non. Utilisateur sans charger leurs paramètres de confidentialité.Cela serait une raison de les séparer.Même si vous avez toujours ajouter la méthode à la classe User comme getUserPrivacy() .Tout encore, vous compliquer les choses pour les performances. –

+1

Vous pouvez avoir tous les éléments dans un tableau, mais utiliser les vues pour empêcher l'ORM de 'voir' toutes les colonnes à la fois –

+1

Vous pourriez oui mais cela ne contredit-il pas un peu? Je suppose que vous utiliseriez ORM en premier lieu pour être organisé entre autres choses. Pourquoi ne pas étendre cela à votre base de données? – KTastrophy

-2

Pourquoi ne pas avoir une table utilisateur et les fonctionnalités table, par exemple:

create table User (id int primary key, name varchar(255) ...)

create table Features ( user_id int, feature varchar(50), enabled bit, primary key (user_id, feature) )

Ensuite, les données de votre table Caractéristiques ressemblerait à ceci:

 
| user_id | feature  | enabled 
| ------------------------------- 
| 291  | show_photos | 1 
| ------------------------------- 
| 291  | show_name | 1 
| ------------------------------- 
| 292  | show_photos | 0 
| ------------------------------- 
| 293  | show_name | 0 
+1

Down voté car ceux-ci ne se développent pas bien –

+1

S'il vous plaît ne pas aller dans cette direction. Ça ne change pas, il est impossible de bien faire des recherches, ça ne peut pas être indexé, c'est une mauvaise idée. Juste google EAV. C'est un modèle de mal-conception si commun qu'il a son propre nom. –

+0

Ce motif de mal-conception est si mauvais, il a son propre nom - EAV. Google toutes les histoires d'horreur ou chercher d'autres messages/commentaires sur SO par moi. –

4

Il est préférable de mettre tous les attributs dans le même tableau.

Si vous commencez à stocker des noms d'attributs dans une table, vous stockez des métadonnées dans votre base de données, qui rompt la première forme normale. En outre, les conserver tous dans la même table simplifie vos requêtes.

Auriez-vous plutôt:

SELECT show_photos FROM User WHERE user_id = 1 

Ou

SELECT up.show_photos FROM User u 
LEFT JOIN UserPrivacy up USING(user_id) 
WHERE u.user_id = 1 

Les relations sont de bien, mais les garder pour associer des entités distinctes et 1-> N relations.

Il y a une limite au nombre de colonnes, et seulement si vous pensez que vous pourriez atteindre cette limite, feriez-vous autre chose.

Il existe des raisons légitimes de stocker des paires de valeurs de nom dans une table distincte, mais la crainte d'ajouter des colonnes n'en fait pas partie. Par exemple, la création d'une table de valeurs de nom peut, dans certaines circonstances, faciliter l'interrogation d'une liste d'attributs. Cependant, la plupart des moteurs de bases de données, y compris PDO en PHP, incluent des méthodes de réflexion grâce auxquelles vous pouvez facilement obtenir une liste de colonnes pour une table (attributs pour une entité).

Veuillez également noter que votre champ id sur User doit être user_id, pas seulement id, à moins que vous n'utilisiez Ruby, qui force seulement l'identifiant. 'User_id' est préféré car avec id juste, votre joint ressemble à ceci:

ON u.id = up.user_id 

Ce qui semble étrange, et la façon préférée est la suivante:

ON u.user_id = up.user_id 

ou plus simplement:

USING(user_id) 

N'ayez pas peur d'ajouter un autre attribut. C'est normal, et ça va.

+0

Pas de vote négatif Marcus, mais je ne suis pas d'accord. L'ajout d'une colonne à une table dans une base de données de production est une affaire assez importante. En ce qui concerne les ID, bien que cela a été débattu un peu ici sur le 'débordement;) – n8wrl

+1

@ n8wrl, Merci pour l'entrée. Cela dépend du système si c'est un gros problème. Si le système est trop occupé, vous pouvez attendre la prochaine fenêtre de maintenance ou les heures creuses. Il est préférable de prendre le coup unique, qui évolue mieux que le code supplémentaire et le travail requis pour gérer l'autre système. –

+2

n8wrl, l'ajout d'une colonne à une grande table prod est FAR préférable à l'utilisation d'une table EAV. EAV tables sont plus de travail à maintenir (gee je n'ai aucune idée de la façon dont les jointures je vais devoir faire pour obtenir les données) .et requête et sont des tueurs de performance. – HLGEM

0

Comme cela semble être une à une relation, je normalement tout garder dans une table à moins que:

Vous seriez près de la limite du nombre d'octets qui peuvent être stockés dans une rangée - puis vous devriez le séparer.

Ou si vous interrogez normalement la table principale séparément et n'avez pas besoin de ces champs la plupart du temps.

0

Si certaines colonnes est (pas identifiable or dependent sur le primary key) ou (valeurs d'un ensemble definite/fixed est utilisé repeatedly) de la table font une table différente pour les colonnes et maintenir une relation biunivoque.

Questions connexes