Очень часто встречается ситуация, когда в базе данных необходимо хранить уйму битовых полей. Банальными решениями, конечно же, будут вставка необходимых колонок, несущих булевый смысл или хранение строки с перечислением всех необходимых сущностей. Но оба решения видятся мне громоздкими, не производительными и не гибкими. Более элегантным видится хранение булевых значений в одном целочисленном поле. Идея, конечно же, далеко не нова, но опишу её по-своему.
Итак, идея достаточно проста. Каждое целое число, которое является степенью двойки, имеет уникальную единицу в соответствующем этому числу месте. Поясню на Python:
>>> for i in range(9):
p = pow(2, i)
print '%d\t%11s' % (p, bin(p))
1 0b1
2 0b10
4 0b100
8 0b1000
16 0b10000
32 0b100000
64 0b1000000
128 0b10000000
256 0b100000000
Т.е. всем необходимым булевым значениям мы сопоставляем целое число степени двойки отличное от нуля. К примеру:
CHOICES = (
(1, 'Значение 1'),
(2, 'Значение 2'),
(4, 'Значение 3'),
(8, 'Значение 4'),
(16, 'Значение 5'),
(32, 'Значение 6'),
(64, 'Значение 7'),
# etc
)
и храним в базе данных лишь одно целочисленное поле, по которому и выбирать быстрее, и искать.
Организовать совокупность полей можно битовым оператором |, т.е.
>>> 1|2 3 >>> 4|16|64 84
А проверить булевый флаг можно так:
>>> bool(84&16) True >>> bool(84&64) True >>> bool(84&4) True >>> bool(84&0) False >>> bool(84&32) False
Надо сказать, что работать с целыми числами программы будут гораздо быстрее, чем со строками. И битовые операции быстрее обычных. Так что и здесь преимущества.
Область применения данной методики не ограничивается лишь базами данных. Данный способ упаковки булевых значений применим в любом коде.
Отправить комментарий