39 votes

Indicateurs dans les lignes d'une base de données, meilleures pratiques

Je demande ça par curiosité. Fondamentalement, ma question est de savoir quand vous avez une base de données qui a besoin d'une entrée de ligne pour avoir des choses qui agissent comme des drapeaux, quelle est la meilleure pratique? Un bon exemple de ce serait les badges sur un débordement de pile ou le système d'exploitation de champ dans bugzilla. Tout sous-ensemble de drapeaux peuvent être définis pour une entrée donnée.

Habituellement, je ne le c et le c++ de travail, donc ma réaction instinctive est d'utiliser un entier non signé de champ comme un ensemble de bits qui peut être retourné... Mais je sais que ce n'est pas une bonne solution pour plusieurs raisons. Le plus évident est l'échelle de capacité, il y aura une dure limite supérieure sur le nombre de drapeaux que je peux avoir.

Je peux aussi penser à un couple de d'autres solutions à l'échelle de mieux, mais qui aurait des problèmes de performances, car ils nécessitent plusieurs sélectionne pour obtenir toutes les informations.

Alors, quelle est la "bonne" façon de faire cela?

34voto

Jeremiah Peschka Points 4756

D'une manière générale, j'évite les champs de masques de bits. Ils sont difficiles à lire à l'avenir et nécessitent une connaissance beaucoup plus approfondie des données pour être compris.

La solution relationnelle a été proposée précédemment. Étant donné l'exemple que vous avez décrit, je créerais quelque chose comme ceci (dans SQL Server):

 
CREATE TABLE Users (
  UserId INT IDENTITY(1, 1) PRIMARY KEY,
  FirstName VARCHAR(50),
  LastName VARCHAR(50),
  EmailAddress VARCHAR(255)
);

CREATE TABLE Badges (
  BadgeId INT IDENTITY(1, 1) PRIMARY KEY,
  [Name] VARCHAR(50),
  [Description] VARCHAR(255)
);

CREATE TABLE UserBadges (
  UserId INT REFERENCES Users(UserId),
  BadgeId INT REFERENCES Badges(BadgeId)
);
 

30voto

Daniel Spiewak Points 30706

Si vous avez vraiment besoin d'une sélection illimitée à partir d'un ensemble fermé de drapeaux (par exemple des badges stackoverflow), la "manière relationnelle" serait de créer une table de drapeaux et une table distincte qui relie ces drapeaux à vos entités cibles. Ainsi, utilisateurs, drapeaux et usersToFlags.

Cependant, si l'efficacité de l'espace est une préoccupation sérieuse et que la capacité de requête ne l'est pas, un masque non signé fonctionnerait presque aussi bien.

5voto

Dan Udey Points 1994

Pour de nombreux cas, cela dépend de beaucoup de choses, comme votre base de données back-end. Si vous utilisez MySQL, par exemple, le JEU de type de données est exactement ce que vous voulez.

Fondamentalement, c'est juste un masque de bits, avec des valeurs attribuées à chaque bit. MySQL prend en charge jusqu'à 64 bits de valeurs (sens de 64 bascule). Si vous n'avez besoin que de 8, alors il ne faut octets par ligne, ce qui est assez impressionnant d'épargne.

Si vous honnêtement avoir plus de 64 valeurs dans un seul champ, votre champ peut être de plus en plus complexes. Vous pouvez élargir ensuite à la GOUTTE de type de données, qui est juste un raw ensemble de bits que MySQL n'a pas de compréhension inhérente de. Grâce à lui, vous pouvez créer un nombre arbitraire de champs de bits que MySQL est heureux de les traiter comme binaire, hexadécimal, décimal ou valeurs, cependant vous avez besoin. Si vous avez besoin de plus de 64 options, créer autant de champs qu'il est nécessaire pour votre application. L'inconvénient est qu'il est difficile de les rendre lisibles par un humain. Le type de données BIT est également limité à 64 ans.

5voto

Seun Osewa Points 3243

Un Très Approche Relationnelle

Pour les bases de données sans le type de jeu, vous pouvez ouvrir une nouvelle table pour représenter l'ensemble des entités pour lesquelles chaque indicateur est défini.

E. g. pour un Tableau des "Étudiants" vous pourriez avoir des tables "RegisteredStudents", "SickStudents", TroublesomeStudents etc. Chaque table aura une seule colonne: la student_id. Ce serait en fait être très rapide si tout ce que vous voulez savoir, c'est où les élèves sont "Enregistrées" ou "Malade", et fonctionne de la même manière dans tous les SGBD.

4voto

vog Points 3334

Si les indicateurs ont des significations très différentes et sont directement utilisées dans des requêtes SQL ou des points de VUE, puis à l'aide de plusieurs colonnes de type BOOLEAN pourrait être une bonne idée.

Mettre chaque drapeau dans une colonne supplémentaire, parce que vous allez les lire et les modifier séparément de toute façon. Si vous souhaitez regrouper les drapeaux, il suffit de donner leurs noms de colonne d'un préfixe commun, c'est à dire au lieu de:

CREATE TABLE ... (
    warnings INTEGER,
    errors   INTEGER,
    ...
)

vous devez utiliser:

CREATE TABLE ... (
    warning_foo BOOLEAN,
    warning_bar BOOLEAN,
    warning_...
    error_foo   BOOLEAN,
    error_bar   BOOLEAN,
    error_...   BOOLEAN,
    ...
)

Bien que MySQL n'a pas de type BOOLÉEN, vous pouvez utiliser la quasi standard de type TINYINT(1) à cet effet, et de le définir uniquement à 0 ou 1.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X