Datentyp zum Speichern eines Arrays von Flags (Bitmap / Bitarray)

15

Ich muss für jeden Datensatz einer Tabelle ein Bit-Array speichern, das die folgenden Operationen unterstützt:

  • Testen, ob ein Bit gesetzt ist, und Setzen eines Bits (unter Verwendung von SQL)

  • Abfragen und Festlegen des Werts mit ADO 2.8 (nicht ADO.NET)

  • Indizierung (um von der Funktion "Deckungsindex" zu profitieren)

Die maximale Anzahl der in diesem Array zu speichernden Bits ist festgelegt, kann jedoch 32 überschreiten . Das heißt, eine einfache int- Spalte funktioniert nicht immer.

Nach dem, was ich bisher gesehen habe, sind meine Optionen:

  1. Verwenden Sie mehrere int- Spalten
  2. Benutze bigint (funktioniert solange die Anzahl der Bits <= 64 ist)
  3. Verwenden Sie die Binärdatei
  4. ?

Die erste Option würde funktionieren, erfordert jedoch einige Umgestaltungen im Code, der auf die Daten zugreift. Die zweite Option ist nur eine vorübergehende Erleichterung, und nach meinen bisherigen Recherchen bin ich mir nicht sicher, ob ADO mit bigint so gut funktioniert . Ich habe keine Erfahrung mit Binärdateien und kenne keine anderen Optionen.

Welchen Datentyp würden Sie angesichts der Anforderungen wählen?

krlmlr
quelle

Antworten:

12

Ich kann nicht stark genug dafür plädieren, dafür kein einziges Feld zu verwenden.

Momentan beschäftige ich mich mit der Pflege eines sehr großen Datensatzes mit einem bigintBitmaskenfeld und es ist ein bisschen wie ein Leistungs-Albtraum.

Wenn Sie ein einzelnes Bit überprüfen, ist es in Ordnung. Wenn Sie mehr als ein Bit prüfen, verschlechtert sich die Leistung sehr schnell.

Aufgrund der Art der Bitmasken-Ganzzahlen ist die Datenverteilung sehr unausgewogen und Sie erhalten suboptimale Pläne.

Mehrere Bitprüfungen führen zu Bereichs- oder Indexprüfungen mit einer Funktion, die für jede Zeile ausgeführt wird. Es ist ein Chaos.

Meine Problemumgehung war einfach: Ich habe eine Tabelle erstellt, in der die PK für jede zu überprüfende Bedingung gespeichert wird. Dies ist anfangs nicht intuitiv, aber der benötigte Speicherplatz ist gering (Sie speichern nur die PK) und Suchvorgänge sind blitzschnell, insbesondere wenn Sie a verwenden UNIQUE CLUSTERED INDEX.

Sie können beliebig viele Bedingungen hinzufügen, ohne die Haupttabelle zu beeinflussen. Aktualisierungen wirken sich auch nicht auf die Haupttabelle aus.

Die Indizierung ist einfach, da Sie nur alle Nachschlagetabellen einzeln indizieren und da Ihr gruppierter Schlüssel in Ihrer Haupttabelle derselbe ist und alle Ihre Auswertungen merge joinsehr effizient sind.

JNK
quelle
1
Könnten Sie Ihre Problemumgehung etwas genauer erläutern? Ich habe dies gefunden, weil ich versucht habe, dasselbe grundlegende Problem anzugehen, aber nicht sicher bin, wie ich es am besten machen soll.
Joshua Frank
4

Wenn Sie nur eine moderate Anzahl von Wahr / Falsch-Werten speichern müssen, können Sie den bitDatentyp verwenden.

Intern speichert SQL Server bitSpalten, die in Byte "Chunks" gepackt sind. Für bis zu 8 bitSpalten in Ihrer Tabelle speichert SQL diese als gepacktes 1 Byte. 9-16 bitSpalten in 2 Bytes und so weiter.

Es hört sich nicht so an, als würden Sie sich dem Spaltenlimit nähern. Das scheint also ziemlich einfach zu sein. Und natürlich können Sie die Spalten zur besseren Lesbarkeit benennen und alle Indizierungsmöglichkeiten abrufen, die Sie normalerweise hätten (wenn die Flags sehr selektiv sind, können gefilterte Indizes hilfreich sein, wenn Sie auf 2008+ abzielen).

Wenn Sie das Bit-Packen selbst durchführen, ist die Indizierung sehr viel komplizierter (wahrscheinlich berechnete und indizierte bitSpalten, um jede Position der Maske darzustellen ... aber dann haben Sie es schlechter als bitdirekt).

Jon Seigel
quelle