Vor- und Nachteile der Verwendung von Bitmasken in Datenbanken

22

Vor nicht allzu langer Zeit habe ich mit meinem Kollegen gesprochen und er war definitiv gegen die Verwendung von Bitmasken, da es schwierig ist, alle in der Datenbank gespeicherten Werte zu verstehen. Meiner Meinung nach ist es nicht immer eine schlechte Idee, sie zu verwenden, um beispielsweise die Rollen des aktuellen Benutzers zu bestimmen. Andernfalls müssen Sie es in einer separaten Tabelle speichern, was zu einem weiteren JOIN führt. Kannst du mir bitte sagen, ob ich falsch liege? Irgendwelche anderen Nebenwirkungen, Vor- / Nachteile der Verwendung von Bitmasken?

Alex Ovechkin
quelle
2
Es kann sinnvoller sein, die Datenbank Bitmasken intern erstellen zu lassen und die Bits als separate Spalten für Sie darzustellen. Ihre Anforderungen können sich ändern.
Simon Richter
1
Wenn Sie keine Joins verwenden, verwenden Sie Ihre relationale Datenbank nicht wie vorgesehen.
Pieter B

Antworten:

38

Ich arbeite mit einer Anwendung, die Bitmasken zum Speichern von Benutzerrollenzuweisungen verwendet. Es ist ein Schmerz im Hintern. Wenn das mich voreingenommen macht, schuldig wie angeklagt.

Wenn Sie bereits eine relationale Datenbank verwenden, ist dies ein Anti-Pattern, das gegen die meisten relationalen Theorien und alle Normalisierungsregeln verstößt. Wenn Sie Ihren eigenen Datenspeicher erstellen, ist dies möglicherweise keine so schlechte Idee.

Es werden zu viele Tabellen verknüpft, aber dafür werden relationale Datenbanken erstellt. Viele haben zusätzliche Funktionen, wenn die Leistung zu einem Problem wird: Indizes, indizierte Ansichten usw. Auch wenn sich die Werte, nach denen Sie suchen, nicht sehr oft ändern, was für Bitmask von Vorteil ist, ist der Mehraufwand für die Verwaltung der Indizierung ziemlich einfach in der Datenbank.

Obwohl die Datenbank Daten gut aggregiert, kann es zu Verzögerungen kommen, wenn Sie beispielsweise komplexe Formeln oder Skalarfunktionen in Datasets einfügen. Sie können das bitweise in Ihrer App tun, aber wenn Sie nur verwandte Daten abrufen (die Rolle (n) eines Benutzers nachschlagen), können Sie nicht ausnutzen, was Ihre Datenspeicherung am besten kann.

Mein letztes Argument dagegen wäre die Einfachheit für andere Entwickler. Sie haben Benutzer, Rollen und Zuordnungen. Es ist eine Menge von vielen Beziehungen (da es mehr als eine Beziehung gibt), die so häufig vorkommt, dass sie einfach zu verwalten sein sollte. Es ist nur CRUD Zeug.

JeffO
quelle
8
Eine relationale Datenbank ist der schlechteste Ort für eine Bitmaske. Die Lagerkosten sind nicht mehr so ​​hoch, dass ein paar Joins und ein zusätzlicher Tisch Sie kaputt machen sollten. Es macht es sicherlich schwieriger, darüber nachzudenken. Speichern Sie die Berechtigungen als Bits (1/0) in der Datenbank in einer eigenen Tabelle und stellen Sie sie im Code mit but-Flags dar. Scheint ziemlich angemessen und machbar. Entwickler bekommen einfache Flags und dbas hat normalisierte Tabellen. Alle sind glücklich.
Mike McMahon
3
Ich war damit einverstanden, eine Anwendung zu unterstützen, die Bitmasken für Benutzerrollen und Berechtigungen in ihrer Datenbank verwendete. Es war ein Albtraum. Bei einer 32-Bit-Ganzzahl gingen uns die Bits aus, sodass jemand die großartige Idee hatte, weitere Bitmasken hinzuzufügen , und dann mit Überlappungen, sodass Bit 4 in einer Spalte Bit 8 in dieser anderen Spalte bedeutete und sie nicht mehr synchron waren. Ja, ja, ja. Es war schwierig zu indizieren, da Indizes diskrete Spaltenwerte und nicht die einzelnen Bits in ihnen speichern, sodass Sie where some_bit_mask & 12 > 0ohne zeilenweisen Scan nicht nach Zeilen suchen können .
Brandon
Am Ende des Tages, ein many-to-many user_role_mapoder user_priv_maphätte Tabelle genügt.
Brandon
@MikeMcMahon, könnten Sie bitte tiefer in das Tabellendesign eintauchen und wie sollte ich es im Code abbilden, um das gewünschte Ergebnis zu erzielen?
Alex Ovechkin
2
@ usr - Sag niemals nie. Sicher können Sie Bitmasken verwenden, aber ich würde sie nicht in einer Anwendung verwenden, die eine relationale Datenbank verwendet. Es gibt wahrscheinlich einige Randfälle beim Umgang mit alten Daten oder ein großes Bedürfnis nach Geschwindigkeit.
JeffO
24

Sie haben die relevanten Vor- und Nachteile bereits benannt:

  • Bitfelder sparen Platz.
  • Sie speichern Daten im Datensatz selbst, sodass Sie keine JOINs benötigen, um sie zu finden. (Einzelne Flag-Felder im Datensatz würden jedoch dasselbe tun.)
  • Sie sind schlecht lesbar, wenn Sie produktiv mit der unformatierten SQL-Ausgabe arbeiten möchten.

Für die Entscheidung, was zu tun ist, sind weitere Informationen erforderlich:

  • Wie knapp ist der Speicherplatz für Ihren Anwendungsfall?
  • Lesen Sie Benutzerrollen tatsächlich so oft, dass die Zeit zum Beitreten zu einem Engpass wird?
  • Werden Sie die SQL-Ausgabe lesen und darauf basierend Entscheidungen treffen - oder ist ein nicht lesbarer Datenbanksatz unerheblich, genauso wie die Tatsache, dass der Maschinencode Ihres Systems nicht lesbar ist?

Sie müssen also die Risikofaktoren erfassen und sie dann gewichten , um festzustellen, ob die Vorteile die Nachteile überwiegen.

Kilian Foth
quelle
Vielen Dank für Ihre Antwort, stimmen Sie völlig mit Ihren Gedanken überein, aber im Allgemeinen ist dies Anti-Muster oder nicht? Und verwenden Sie Masken in Ihren Projekten?
Alex Ovechkin
12
@Alex Es gibt keine "Best Practice", die entscheiden kann, was in Ihrem Fall zu tun ist. Wenn Sie extrem wenig Platz haben, empfiehlt sich die Verwendung von Bitfeldern. Wenn Sie die SQL-Ausgabe in Berichten an den CEO verwenden möchten, empfiehlt es sich, Namen auszusprechen. Aber Sie sind der Einzige, der diese Umstände kennt, daher kann die Community Ihnen kein Rezept geben, das immer gültig ist.
Kilian Foth
Nehmen Sie das Space-Argument als "Gimme". Die Frage, ob eine Bitmaske verwendet werden soll oder nicht, hängt davon ab, ob sie darüber hinaus von Nutzen ist.
Robbie Dee
Müssen Sie auch JEDE Informationen in der Datenbank verarbeiten oder werden sie immer in eine Anwendung eingelesen, bevor Sie sie verwenden?
Ian
1
"Werden Sie die SQL-Ausgabe lesen und darauf basierend Entscheidungen treffen - oder ist ein nicht lesbarer Datenbanksatz unerheblich, genauso wie die Tatsache, dass der Maschinencode Ihres Systems nicht lesbar ist?" Ich kann wohl nicht für alle Entwickler sprechen, aber wenn ich entwickle, ist es sehr häufig, dass ich Daten aus der Datenbank auswähle, um etwas zu verstehen oder zu überprüfen. Daher würde ich sagen, dass die Antwort normalerweise "Ja, jemand wird" lautet.
jpmc26
18

Wenn Sie wirklich, wirklich , wirklich für Speicherplatz geschnallt, dann sind Sie möglicherweise Bitmaps für Benutzerberechtigungen prüfen. Wenn Sie sich Sorgen um die Leistung machen, vergessen Sie sie vollständig, da das Auseinandernehmen tatsächlich langsamer ist. Sie können ein Bitmap-Feld nicht sinnvoll indizieren , was zu Datenbanktabellen-Scans führt, die [fast] immer einen Performance-Killer darstellen.

Sofern Sie nicht Amazon oder Netflix sind, ist die Datenmenge , die für die Benutzerberechtigungen erforderlich ist, im Vergleich zu allen anderen Daten , die Sie besitzen , vernachlässigbar.

Jedes seriöse DBMS kann mit diesem "zusätzlichen Join" umgehen, ohne zu blinken.

Phill W.
quelle
7
+1: Die guten relationalen Datenbanken werden von Leuten entwickelt, die wirklich, wirklich, wirklich gut darin sind, was sie tun. Jeder, der das letzte Maß an Leistung erbringen möchte, das Sie möglicherweise durch die Verwendung von Bitfeldern erzielen, muss sich nicht mit dieser Frage befassen. Modellieren Sie die Daten und suchen Sie dann die Teile, die nicht funktionieren.
Blrfl
Durch die Verknüpfung wird der Anwendungscode komplexer, und es kommt darauf an, WO die Rollen verarbeitet werden.
Ian
4
@Ians Join scheint nicht komplexer zu sein, als zu wissen, wie die bitmaskierten Berechtigungen zu entschlüsseln sind.
Brad
@Brad, Stellen Sie sich eine Aufzählung vor, die eine Reihe von Flags in C # ist und deren Wert unverändert in der Datenbank gespeichert ist. Einfacher kann C # nicht sein. Wenn ein Join verwendet wird, muss der C # -Code mit einer Beziehung von „1 zu vielen“ fertig werden.
Ian
Ich sollte auch hinzufügen, dass die meisten Datenbanken, wenn Sie mehrere boolesche Spalten in einer Tabelle haben, herausfinden, wie sie auf möglichst wenig Speicherplatz komprimiert werden können, und sich um das Bit-Twiddling für Sie kümmern.
Blrfl
8

Damals, als Lagerung teuer war, war der Segen mit Bitmasken, dass sie Platz sparten. In Zeiten von Big Data war dies nicht mehr das Problem.

Das Beispiel, das Sie zitieren, zu nehmen - Rollen als Bitmaske zu speichern, wäre aus Sicht des Datenbankdesigns ein gewisser Codegeruch, da dies gegen die erste Normalform verstoßen würde . In diesem Sinne sind sie ein Anti-Muster.

Trotzdem muss es nicht das eine oder andere sein. Sie können die Daten als Bitmaske speichern und dann über eine Ansicht verfügen, mit der die Benutzerrollen im Handumdrehen abgerufen werden können. Sie haben dann auch den Vorteil, auf einen Blick zu überprüfen, welche Benutzer die gleichen Rollen haben.

Robbie Dee
quelle
2

Der einzige Vorteil bei der Verwendung von Bitmasken besteht darin, dass die Bedeutung der Bitfelder nicht statisch ist. Relationale Tabellen funktionieren nur dann gut, wenn Sie im Voraus wissen, welche Felder sich in einem Datensatz befinden: Sie müssen die Felder in der CREATE TABLEDDL-Anweisung schließlich identifizieren .

Wenn die Bedeutung jedes Bitfelds zur Laufzeit konfigurierbar ist oder anderweitig nicht im Voraus bekannt ist, ist es möglicherweise sinnvoll, Boolesche Werte als Bitfeld zu speichern. Selbst dann ist es möglich , eine Tabelle mit beliebigen Feldern zu definieren: field_1, field_2usw. Dies gibt Ihnen ein sauberere relationales Design, wenn auch noch nicht ideal. Ob dies einem Bitfeld vorgezogen wird, ist weitgehend Ansichtssache, da keine der beiden Lösungen ideal ist.

Wenn Sie wissen, was die Bits während der Entwicklung darstellen, erstellen Sie Felder für jedes Bit und geben Sie ihnen aussagekräftige Namen .

Achten Sie nur auf den inneren Plattformeffekt . Wenn Sie am Ende beliebige, aber gut typisierte Felder definieren, ist das eine Sache, aber wenn Sie zu weit gehen, werden Sie eine relationale Datenbank neu erfinden ... innerhalb einer relationalen Datenbank.


quelle
2

Ich bin ambivalent zu Bitmasken. Ich finde, dass die meisten ihrer Kritiker binär und hexadezimal nicht verstehen. Verwenden Sie zur Verdeutlichung gute Mnemonik.

Ein Vorteil, der oben nicht erwähnt wurde, ist die Möglichkeit, Bitmasken eine neue Bedeutung zu verleihen, ohne dass eine neue Spalte hinzugefügt werden muss. Unsere DB-Designer (die mir vorausgegangen sind) haben sie in einer Tabelle, die jetzt täglich 5 Millionen neue Datensätze erhält. Das Hinzufügen einer neuen Spalte, um ein neues Verhalten darzustellen, würde viel Zeit in Anspruch nehmen, während das Definieren eines neuen Bits (33 von 64) keine erneute Tabellenerstellung erfordert.

Nein, Bitmasken können nicht indiziert werden, aber das Erstellen von 33 Indizes wäre lächerlich und würde das Einfügen in einen Crawl verlangsamen. Tabellensuchen verwenden die Indizes "Eigentümer" für Datums- und Datensatzangaben, daher werden Indizes für diese Bitmaske, wenn möglich, niemals verwendet.

GB
quelle
Es ist ein interessanter Fall. Ich nehme an, Sie könnten dasselbe auf koschere und explizite Weise erreichen, indem Sie "Ersatz" -Spalten in der Tabelle definieren und diese dann nach Bedarf in Betrieb nehmen. Sie können diese Spalten dann zumindest selektiv indizieren, falls Sie dies wünschen.
Steve
1

Wenn das Ziel nur darin besteht, Speicherplatz zu sparen, halte ich das für eine schlechte Idee:

  • Schauen Sie sich die Kosten des GB heute an,
  • Vergleichen Sie dies mit den Zeitkosten derjenigen, die Berichte und Fragen schreiben und herausfinden müssen, was sich auf dem Gebiet befindet und wie ein bestimmtes Problem gelöst werden kann. Der Kosten-Nutzen-Vergleich könnte auf der falschen Seite enden.
  • Wenn Sie mit einer SQL-Datenbank arbeiten, benötigen die zusätzlichen Bitzugriffsoperationen, die in vielen Abfragen erforderlich sind, möglicherweise auch mehr Rechenzeit als erforderlich

Es gibt jedoch einige Fälle, die die Verwendung von Bitfeldern rechtfertigen können:

  • Wenn Ihre Bits eine komplexe Menge von Flags darstellen, die Sie immer als Ganzes behandeln,
  • noch mehr, wenn Sie einige Pattern Matching-Algorithmen auf diese Sets anwenden müssen,
  • und insbesondere dann, wenn diese Daten nicht zu den am häufigsten verwendeten Auswahlkriterien gehören.
Christophe
quelle