Il n'y a pas si longtemps, j'ai parlé à mon collègue et il était définitivement contre l'utilisation de masques de bits car il est difficile de comprendre toutes les valeurs stockées dans la base de données. À mon avis, ce n'est pas toujours une mauvaise idée de les utiliser, par exemple pour déterminer les rôles de l'utilisateur actuel. Sinon, vous devez le stocker dans une table distincte, ce qui entraînera une autre JOIN. Pouvez-vous me dire si je me trompe? Y a-t-il d'autres effets secondaires, avantages/inconvénients de l'utilisation de masques de bits?
Je travaille avec une application qui utilise des masques de bit pour stocker les attributions de rôles utilisateur. C'est une douleur dans le cul. Si cela me rend partial, coupable comme accusé.
Si vous utilisez déjà une base de données relationnelle, il s'agit d'un anti-modèle qui viole la plupart des théories relationnelles et toutes les règles de normalisation. Lorsque vous créez votre propre stockage de données, ce n'est peut-être pas une si mauvaise idée.
Il y a une telle chose que trop de tables sont jointes, mais des bases de données relationnelles sont construites pour gérer cela. Beaucoup ont des fonctionnalités supplémentaires si les performances deviennent un problème: index, vues indexées, etc. Même si les valeurs que vous recherchez ne changent pas très souvent, ce qui est un avantage pour Bitmask, la surcharge de gestion de l'indexation est assez facile sur la base de données.
Bien que la base de données fasse un bon travail d'agrégation de données, elles peuvent devenir lentes lorsque vous commencez à introduire des choses comme des formules complexes ou des fonctions scalaires dans des ensembles de données. Vous pouvez le faire au niveau du bit dans votre application, mais si tout ce que vous faites est d'obtenir des données connexes (rechercher les rôles d'un utilisateur), vous ne profitez pas de ce que votre stockage de données fait de mieux.
Mon dernier argument contre cela serait la simplicité pour les autres développeurs. Vous avez des utilisateurs, des rôles et des affectations. C'est un ensemble de relations plusieurs-à-plusieurs (car il y a plus d'une relation) qui est si commun qu'il devrait être facile à gérer. C'est juste des trucs CRUD.
Vous avez déjà nommé les avantages et les inconvénients pertinents:
Décider quoi faire nécessite plus d'informations:
Donc, ce que vous avez à faire est de rassembler les facteurs de risque, puis poids eux, pour voir si les avantages l'emportent sur les inconvénients.
Si vous êtes vraiment, vraiment , vraiment à court d'espace disque, alors vous pourrait considérer les bitmaps pour les autorisations des utilisateurs. Si les performances vous inquiètent, oubliez-les complètement, car les séparer sera en fait plus lent. Vous ne pouvez pas indexer un champ bitmap de manière significative, ce qui entraîne des analyses de table de base de données, qui sont [presque] toujours un tueur de performances.
Sauf si vous êtes Amazon ou Netflix, la quantité de données impliquées dans les autorisations utilisateur sera négligeable par rapport à tout ce que vous détenez.
Tout SGBD sérieux peut gérer cette "jointure supplémentaire" sans même clignoter.
À l'époque où le stockage était coûteux, l'avantage des masques à mors était qu'ils avaient économisé de l'espace. À l'époque du Big Data, ce n'était plus le problème.
Prenons l'exemple que vous citez - avoir des rôles stockés sous forme de masque de bits serait une sorte d'odeur de code du point de vue de la conception d'une base de données car cela violerait première forme normale . En ce sens, ils sont un anti-modèle.
Cela étant dit, il n'est pas nécessaire que ce soit l'un ou l'autre. Vous pouvez stocker les données sous forme de masque de bits, puis avoir une vue qui peut extraire les rôles d'utilisateur à la volée. Vous auriez alors également l'avantage de vérifier en un coup d'œil quels utilisateurs avaient les mêmes rôles.
Le seul avantage de l'utilisation des masques de bits est que la signification des champs de bits n'est pas statique. Les tables relationnelles ne fonctionnent bien que si vous savez à l'avance ce que chaque champ est sur un enregistrement: vous devez identifier les champs dans le CREATE TABLE
Instruction DDL après tout.
Si la signification de chaque champ de bits est configurable au moment de l'exécution, ou autrement inconnue à l'avance, alors est logique de stocker les booléens sous forme de champ de bits. Même alors, il est possible de définir une table avec des champs arbitraires: field_1
, field_2
, etc. Cela vous donne une conception relationnelle plus nette, bien que toujours pas idéale. Que ce soit préférentiel à un champ de bits est en grande partie une question d'opinion, car aucune des solutions n'est idéale.
Si vous savez ce que les bits représentent pendant le développement, créez des champs pour chaque bit et donnez-leur des noms significatifs .
Faites juste attention à effet de plateforme interne . Si vous finissez par définir des champs arbitraires mais bien typés, c'est une chose, mais si vous allez trop loin, vous réinventerez une base de données relationnelle ... à l'intérieur d'une base de données relationnelle.
Je suis ambivalent au sujet des bitmasks. Je trouve que la plupart de leurs détracteurs ne comprennent pas le binaire et l'hexadécimal. Pour plus de clarté, utilisez de bons mnémoniques.
Un avantage non mentionné ci-dessus est la possibilité d'ajouter une nouvelle signification aux masques de bits sans l'ajout potentiellement long d'une nouvelle colonne. Nos concepteurs de base de données (qui m'ont précédé) les ont dans un tableau qui obtient maintenant 5 millions de nouveaux enregistrements par jour. L'ajout d'une nouvelle colonne pour représenter un nouveau comportement prendrait beaucoup de temps, tandis que la définition d'un nouveau bit (nous en avons consommé 33 sur 64) ne nécessite aucune reconstruction de table.
Non, les masques de bits ne peuvent pas être indexés, mais la création de 33 index serait ridicule et ralentirait les insertions dans une analyse. Les recherches de table utilisent les dates et enregistrent les index "propriétaires", donc les index sur ce masque de bits, si possible, ne seront jamais utilisés.
Si le but est juste d'économiser de l'espace disque, je pense que c'est une mauvaise idée:
Cependant, il existe certains cas, qui peuvent justifier l'utilisation de champs de bits: