SQL Server: varbinary или int для хранения битовой маски?

Есть ли какое-либо преимущество использования int vs varbinary для хранения битовых масок с точки зрения производительности или гибкости.

Для моих целей я всегда буду выполнять чтение этих битовых масок (без записи или обновления).


person aleemb    schedule 30.04.2009    source источник


Ответы (4)


Вы обязательно должны использовать INT (если вам нужно 32 флага) или BIGINT (для 64 флагов). Если вам нужно больше флагов, вы можете использовать BINARY (но вы, вероятно, также должны спросите себя, зачем вам так много флагов в вашем приложении).

Кроме того, если вы используете интегральный тип, вы можете использовать стандартные побитовые операторы. напрямую без преобразования массива байтов в целочисленный тип.

Если вам нужно больше флагов и вам приходится использовать BINARY, вы теряете встроенную поддержку побитовых операторов и, следовательно, легкую поддержку проверки значений флагов. Я бы, вероятно, перенес проверку значений флагов в клиентское приложение, но если вам удобно программировать на T-SQL, это тоже вариант. Если вы используете C#, у вас есть класс BitArray. с необходимыми операциями, а в Java у вас есть BitSet класс.

person Ronald Wildenberg    schedule 30.04.2009
comment
да, или события меньшего типа, такие как tiny int для меньших битовых масок? Я еще никогда не использовал крошечный int в качестве битовой маски, но это не должно быть проблемой. Инт отлично работает. - person Chad Grant; 01.05.2009
comment
Как мы можем использовать varbinary, когда у нас есть, например, 100 флагов? Можно ли использовать varbinary так же гибко, как int или bigint? Невозможно выполнить побитовую операцию над двумя varbinary. Как мы можем имитировать поведение int-flag? - person aldebaran; 17.12.2013
comment
Я бы использовал для этого BINARY(13) (есть место для 104 бит/флажков). Однако вы теряете встроенную поддержку побитовых операторов. Я обновил свой ответ, чтобы предоставить некоторые варианты. - person Ronald Wildenberg; 17.12.2013

Обычно считается предпочтительным использовать набор битовых столбцов вместо битовой маски. Они соберутся вместе на странице и не займут больше места. Хотя я тоже всегда использую столбец int или bigint, чтобы избежать ввода всех имен столбцов ... но с intellisense я, вероятно, выбрал бы битовые столбцы.

person ahains    schedule 30.04.2009
comment
Я не согласен, битмаски все еще имеют свое место, и это отличный способ оставить ваши параметры открытыми без необходимости рефакторинга вашей БД и SELECTS/VIEWS/SPROCS просто для добавления простого логического значения, они очень гибкие ... просто большинство программистов не понимают какие они в наши дни - person Chad Grant; 01.05.2009
comment
Невежество программистов иногда показывает, что мы делаем хорошие успехи, абстрагируя низкоуровневые оптимизации внутри движков и фреймворков. ОТДЕЛЬНЫЕ БИТОВЫЕ ПОЛЯ: 1. Эффективно обрабатываются движком (упаковываются вместе, управляются собственным кодом, а не TSQL). 2. Иметь осмысленные имена, делающие ваши запросы более понятными (вместо использования произвольных номеров битовых индексов). 3. На них можно размещать индексы, ускоряющие запросы. 4. Может иметь индивидуально настраиваемые значения по умолчанию. 5. Легче преобразовать в более крупный тип позже, если вы решите, что поле нуждается в более чем двух состояниях. и т.п. - person Triynko; 28.10.2010
comment
Точно. Битмаски в SQL просто убивают то, что может сделать SQL - вы никогда не сможете эффективно запрашивать их. Следовательно, их не следует использовать. - person TomTom; 28.10.2010
comment
Есть по крайней мере одно обстоятельство, когда поле битовой маски необходимо: индекс ограничен 16 столбцами, которые вы можете превысить с помощью группы флагов или серии упакованных значений. - person ; 18.12.2013
comment
@JonofAllTrades это ограничение относится только к столбцам, составляющим ключ индекса (вы можете добавлять биты как включаемые столбцы и по-прежнему основываться на них). Были ли у вас случаи, когда было полезно иметь более 16 логических значений в ключе индекса? - person ahains; 19.12.2013
comment
@ahains: Нет, но у меня были случаи, когда я хотел создать ключ для более чем 16 полей, включая семь небольших целых чисел. В итоге я упаковал семь по три бита в один 32-битный INT. Прекрасно работает. Случай конечно необычный, но действующий. - person ; 20.12.2013
comment
@Triyko Имена столбцов не обязательно заменяют правильное бизнес-определение содержимого столбца. Кроме того, иногда вы имеете дело с наборами битов из внешней системы (например, ACE файловой системы NTFS), и их проще сохранить в таком виде. - person Chalky; 11.08.2015

Что ж, учитывая, что int имеет меньше места для хранения и, как правило, с ним немного проще работать, я не уверен, зачем вам использовать varbinary.

person NotMe    schedule 30.04.2009

Обычно я согласен с ответом @hainstech об использовании битовых полей, потому что вы можете явно назвать каждое битовое поле, чтобы указать, что оно должно хранить. Однако я не видел практического подхода к сравнению битовых масок с битовыми полями. С помощью побитовых операторов SQL Server (&, | и т. д.) легко узнать, установлен ли диапазон флагов. Намного больше работы, чтобы сделать это с операторами равенства против большого количества битовых полей.

person Rick    schedule 30.04.2009
comment
За исключением... шляпных побитовых операторов FORCE A TABLE SCAN, которые убивают производительность, в то время как отдельные битовые поля могут быть эффективно запрошены. - person TomTom; 28.10.2010