Тип даних для зберігання масиву прапорів (растровий / бітовий масив)


15

Мені потрібно зберігати бітовий масив для кожного запису таблиці, підтримуючи такі операції:

  • Тестування, якщо встановлено біт, і встановлення біта (за допомогою SQL)

  • Запит і встановлення значення за допомогою ADO 2.8 (не ADO.NET)

  • Індексація (щоб отримати перевагу від функції "індекс покриття")

Максимальна кількість бітів, що зберігаються в цьому масиві, фіксована, але може перевищувати 32 . Тобто, простий стовпець int не завжди працює.

З того, що я бачив досі, мої варіанти:

  1. Використовуйте кілька стовпців int
  2. Використовуйте bigint (працює до тих пір, поки кількість бітів <= 64)
  3. Використовуйте двійкове
  4. ?

Перший варіант буде працювати, але вимагає зовсім небагато рефакторингу в коді, який отримує доступ до даних. Другий варіант - лише тимчасове полегшення, і з моїх пошуків поки що я не надто впевнений, чи добре працює ADO з bigint . Я не маю досвіду роботи з бінарними і не знаю жодних інших варіантів.

Який тип даних ви б обрали, враховуючи вимоги?

Відповіді:


12

Я не можу досить відстоювати, щоб не використовувати для цього жодного поля.

В даний час я маю справу з підтриманням дуже великого набору даних з bigintполем біткої маски, і це трохи кошмар продуктивності.

Якщо ви перевірите один біт, це добре. Якщо ви перевірите більше, ніж один біт продуктивність знижується дуже швидко.

Зважаючи на характер цілих чисел масок, розподіл даних буде дуже незбалансованим, і ви отримаєте неоптимальні плани.

Багаторазові перевірки призводять до сканування діапазону або індексу, функція працює проти кожного рядка. Це безлад.

Моє вирішення було простим - я склав таблицю для зберігання ПК для кожної з умов, що перевіряються. Спочатку це контр-інтуїтивно, але потрібний простір низький (ви зберігаєте лише ПК), і пошуки блискавки швидко проходять, особливо якщо ви користуєтесь UNIQUE CLUSTERED INDEX.

Ви можете додати скільки завгодно умов, не впливаючи на основну таблицю, і оновлення також не впливають на вашу основну таблицю.

Індексація проста, оскільки ви просто індексуєте всі таблиці пошуку окремо, а оскільки ваш кластерний ключ є однаковим у вашій головній таблиці, а підсумки всіх ваших оцінок merge joinє дуже ефективними.


1
Не могли б ви детальніше зупинитися на своєму вирішенні? Я знайшов це, тому що намагаюся вирішити ту саму основну проблему, але не знаю, як найкраще це зробити.
Джошуа Френк

4

Якщо все, що потрібно для зберігання, - це помірна кількість істинних / хибних значень, ви можете використовувати bitтип даних.

Внутрішньо SQL Server зберігає bitстовпчики, упаковані в байти "шматки". Таким чином, до 8 bitстовпців у вашій таблиці SQL зберігає, як упакований 1 байт; 9-16 bitстовпців у 2 байти тощо.

Це не здається, що ви збираєтесь наблизитись до межі стовпця, тому це здається досить прямим. І звичайно, зберігаючи їх добре розділеними, як це дає змогу називати стовпці для читабельності та отримувати всі можливості індексації, які ви зазвичай мали б (якщо прапори є високоселективними, відфільтровані індекси можуть бути корисними, якщо ви можете орієнтуватися на 2008+).

Якщо самостійно виконати пакування бітів, це зробить набагато більш складним проведення індексації (можливо, обчислювані та індексовані bitстовпці представляють кожну позицію маски ... але тоді ви гірше проти використання bitбезпосередньо).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.