Herrliche Frage!
Lassen Sie uns zunächst einige Annahmen über "besser" treffen.
Ich gehe davon aus, dass Sie sich nicht viel um Speicherplatz kümmern - eine Bitmaske ist aus Platzgründen effizient, aber ich bin mir nicht sicher, ob dies wichtig ist, wenn Sie SQL Server verwenden.
Ich gehe davon aus, dass Ihnen Geschwindigkeit wichtig ist. Eine Bitmaske kann bei der Verwendung von Berechnungen sehr schnell sein - Sie können jedoch keinen Index verwenden, wenn Sie die Bitmaske abfragen. Dies sollte nicht allzu wichtig sein, aber wenn Sie wissen möchten, welche Benutzer Zugriff erstellen, ist Ihre Abfrage ungefähr so
select * from user where permsission & CREATE = TRUE
(Ich habe heute unterwegs keinen Zugriff auf SQL Server). Diese Abfrage kann aufgrund der mathematischen Operation keinen Index verwenden. Wenn Sie also eine große Anzahl von Benutzern haben, ist dies ziemlich schmerzhaft.
Ich gehe davon aus, dass Ihnen die Wartbarkeit am Herzen liegt. Unter dem Gesichtspunkt der Wartbarkeit ist die Bitmaske nicht so aussagekräftig wie die zugrunde liegende Problemdomäne wie das Speichern expliziter Berechtigungen. Sie müssten mit ziemlicher Sicherheit den Wert der Bitmaskenflags über mehrere Komponenten hinweg synchronisieren - einschließlich der Datenbank. Nicht unmöglich, aber Rückenschmerzen.
Sofern es keine andere Möglichkeit gibt, "besser" zu bewerten, würde ich sagen, dass die Bitmaskenroute nicht so gut ist wie das Speichern der Berechtigungen in einer normalisierten Datenbankstruktur. Ich bin nicht damit einverstanden, dass es "langsamer ist, weil Sie einen Join durchführen müssen" - wenn Sie nicht über eine völlig funktionsgestörte Datenbank verfügen, können Sie dies nicht messen (während das Abfragen ohne den Vorteil eines aktiven Index spürbar werden kann langsamer mit sogar ein paar tausend Datensätzen).
Persönlich würde ich eine assoziative Tabelle verwenden.
Ein Bitmaskenfeld ist sehr schwer abzufragen und zu verbinden.
Sie können dies jederzeit Ihrer C # -Flaggen-Aufzählung zuordnen, und wenn die Leistung steigt und die Datenbank refaktoriert wird.
Lesbarkeit über vorzeitige Optimierung;)
quelle
Speichern Sie die Berechtigungen normalisiert (dh nicht in einer Bitmaske). Dies ist offensichtlich keine Voraussetzung für Ihr Szenario (insbesondere wenn sich die Berechtigungen nicht häufig ändern), macht das Abfragen jedoch viel einfacher und offensichtlicher.
quelle
Es gibt keine endgültige Antwort . Tun Sie also , was für Sie funktioniert . Aber hier ist mein Haken:
Verwenden Sie Option 1, wenn
Verwenden Sie Option 2, wenn
quelle
Das einzige Mal, dass ich mir vorstellen kann, wann ich ein Bitmaskenfeld zum Speichern von Berechtigungen verwenden würde, ist, wenn Sie wirklich sehr eingeschränkt sind, wie viel physischen Speicher Sie haben ... wie vielleicht auf einem alten mobilen Gerät. In Wahrheit ist die Menge an Speicher, die Sie sparen, es nicht wert. Selbst bei Millionen von Benutzern ist der Festplattenspeicher billig, und Sie können Berechtigungen usw. viel einfacher erweitern, indem Sie den Nicht-Bitmasken-Ansatz verwenden (hier geht es darum, zu melden, wer über welche Berechtigungen verfügt usw.).
Eines der größten Probleme, auf das ich gestoßen bin, ist das Zuweisen von Benutzerberechtigungen direkt in der Datenbank. Ich weiß, dass Sie versuchen sollten, die Anwendung zu verwenden, um sich selbst zu verwalten, und nicht viel mit Anwendungsdaten im Allgemeinen, aber manchmal ist es nur notwendig. Wenn die Bitmaske kein Zeichenfeld ist und Sie leicht sehen können, welche Berechtigungen jemand anstelle einer Ganzzahl hat, erklären Sie einem Analysten usw., wie Sie jemandem Schreibzugriff usw. gewähren können, indem Sie das Feld aktualisieren ..... und beten Ihre Arithmetik ist korrekt.
quelle
Es ist nützlich, wenn sie sich in ihrer Struktur nicht ändern und immer zusammen verwendet werden. Auf diese Weise haben Sie kleine Roundtrips zum Server. Sie sind auch in Bezug auf die Leistung gut, da Sie alle Rechte in einer einzigen Zuweisung einer Variablen beeinflussen können.
Ich persönlich mag sie nicht ... In einigen leistungsintensiven Anwendungen werden sie immer noch verwendet. Ich erinnere mich, dass ich mit diesen eine Schach-KI implementiert habe, weil man ein Board in einem einzigen Vergleich bewerten konnte. Es ist mühsam, damit zu arbeiten.
quelle
Ich würde es immer normal speichern, es sei denn, die Datenbank enthält lediglich den Datensatz für Sie, und Sie werden damit nie etwas anderes tun, als abzurufen und zu speichern. Ein Szenario hierfür ist, wenn beim Anmelden die Berechtigungszeichenfolge Ihres Benutzers abgerufen und im Servercode verarbeitet und zwischengespeichert wird. In diesem Fall ist es wirklich nicht so wichtig, dass es denormalisiert ist.
Wenn Sie es in einer Zeichenfolge speichern und versuchen, auf DB-Ebene daran zu arbeiten, müssen Sie etwas turnen, um die Berechtigungen für Seite X zu erhalten, was schmerzhaft sein kann.
quelle
Ich rate aus folgenden Gründen von der Verwendung einer Bitmaske ab:
Abhängig von Ihren Abfragemustern, dem geplanten Funktionsumfang und der Datenverteilung würde ich mich für Option 1 entscheiden, oder sogar für etwas Einfaches wie:
user_permissions( user_id ,read ,create ,download ,print ,approve ,primary key(user_id) );
Das Hinzufügen einer Spalte ist eine Schemaänderung, aber ich vermute, dass für das Hinzufügen eines Privilegs "Bereinigen" Code erforderlich ist, sodass die Privilegien möglicherweise nicht so dynamisch sein müssen, wie Sie denken.
Wenn Sie eine kranke Datenverteilung haben, z. B. wenn 90% der Benutzer keine einzige Berechtigung haben, funktioniert das folgende Modell ebenfalls einwandfrei (fällt jedoch bei größeren Scans auseinander (ein 5-Wege-Join gegenüber einer einzelnen vollständigen Tabelle) Scan).
user_permission_read( user_id ,primary key(user_id) ,foreign key(user_id) references user(user_id) ) user_permission_write( user_id ,primary key(user_id) ,foreign key(user_id) references user(user_id) ) user_permission_etcetera( user_id ,primary key(user_id) ,foreign key(user_id) references user(user_id) )
quelle
Ihre Abfragen werden mithilfe einer Flags-Aufzählung (Bitmaske) schneller ausgeführt, da Sie der zugeordneten Tabelle keinen Join hinzufügen müssen, um den Wert zu verstehen.
quelle
USER_PERMISSION
Tabelle, ist es unwahrscheinlich, dass der Leistungsunterschied von Bedeutung ist - dies ist wahrscheinlich nicht die Engpassoperation - und es gibt eine erheblicher Klarheitsverlust im Code.