Type de données pour stocker un tableau d'indicateurs (un tableau bitmap / bit)

15

J'ai besoin de stocker un tableau de bits pour chaque enregistrement d'une table, prenant en charge les opérations suivantes:

  • Tester si un bit est défini et définir un bit (à l'aide de SQL)

  • Interrogation et définition de la valeur à l'aide d'ADO 2.8 (pas d'ADO.NET)

  • Indexation (afin de bénéficier de la fonctionnalité "Covering Index")

Le nombre maximal de bits à stocker dans ce tableau est fixe, mais peut dépasser 32 . Autrement dit, une simple colonne int ne fonctionne pas toujours.

D'après ce que j'ai vu jusqu'à présent, mes options sont les suivantes:

  1. Utiliser plusieurs colonnes int
  2. Utiliser bigint (fonctionne tant que le nombre de bits est <= 64)
  3. Utiliser binaire
  4. ?

La première option fonctionnerait, mais nécessiterait un peu de refactorisation dans le code qui accède aux données. La deuxième option est un soulagement temporaire uniquement, et d'après mes recherches jusqu'à présent, je ne suis pas trop sûr si ADO fonctionne si bien avec bigint . Je n'ai aucune expérience avec binaire et je ne connais aucune autre option.

Quel type de données choisiriez-vous, compte tenu des exigences?

krlmlr
la source

Réponses:

12

Je ne peux pas plaider assez fortement pour ne pas utiliser un seul champ pour cela.

Je suis actuellement en train de gérer un très grand ensemble de données avec un bigintchamp de masque de bits et c'est un peu un cauchemar pour les performances.

Si vous cochez un seul bit, ça va. Si vous cochez plusieurs bits, les performances se dégradent très rapidement.

En raison de la nature des entiers de masque de bits, la distribution des données sera très déséquilibrée et vous obtiendrez des plans sous-optimaux.

Les vérifications de bits multiples entraînent des analyses de plage ou d'index avec une fonction exécutée sur chaque ligne. C'est le bordel.

Ma solution de contournement était simple - j'ai créé un tableau pour stocker le PK pour chacune des conditions à vérifier. C'est contre-intuitif au départ, mais l'espace nécessaire est faible (vous ne stockez que le PK) et les recherches sont rapides comme l'éclair, surtout si vous utilisez un UNIQUE CLUSTERED INDEX.

Vous pouvez ajouter autant de conditions que vous le souhaitez sans affecter votre table principale, et les mises à jour n'affectent pas non plus votre table principale.

L'indexation est simple car vous indexez simplement toutes les tables de recherche individuellement, et puisque votre clé en cluster est la même sur votre table principale et les recherches, toutes vos évaluations sont des merge joins très efficaces.

JNK
la source
1
Pourriez-vous élaborer un peu plus sur votre solution de contournement? J'ai trouvé cela parce que j'essaie de résoudre le même problème de base, mais je ne sais pas comment le faire.
Joshua Frank
4

Si tout ce que vous devez stocker est un nombre modéré de valeurs vraies / fausses, vous pouvez utiliser le bittype de données.

En interne, SQL Server stocke les bitcolonnes regroupées en «morceaux» d'octets. Ainsi, pour un maximum de 8 bitcolonnes dans votre table, SQL le stocke sous la forme d'un octet compressé; 9 à 16 bitcolonnes sur 2 octets, etc.

Il ne semble pas que vous allez approcher de la limite de colonne, donc cela semble assez simple. Et bien sûr, en les gardant bien séparées comme cela vous permet de nommer les colonnes pour la lisibilité et d'obtenir toutes les possibilités d'indexation que vous auriez normalement (si les indicateurs sont très sélectifs, les index filtrés peuvent être utiles si vous pouvez cibler 2008+).

Faire le paquetage vous-même rendra beaucoup plus compliqué l'indexation (probablement des bitcolonnes calculées et indexées pour représenter chaque position du masque ... mais alors vous êtes pire que d'utiliser bitdirectement).

Jon Seigel
la source