Очень часто встречается ситуация, когда в базе данных необходимо хранить уйму битовых полей. Банальными решениями, конечно же, будут вставка необходимых колонок, несущих булевый смысл или хранение строки с перечислением всех необходимых сущностей. Но оба решения видятся мне громоздкими, не производительными и не гибкими. Более элегантным видится хранение булевых значений в одном целочисленном поле. Идея, конечно же, далеко не нова, но опишу её по-своему.
Итак, идея достаточно проста. Каждое целое число, которое является степенью двойки, имеет уникальную единицу в соответствующем этому числу месте. Поясню на 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
Надо сказать, что работать с целыми числами программы будут гораздо быстрее, чем со строками. И битовые операции быстрее обычных. Так что и здесь преимущества.
Область применения данной методики не ограничивается лишь базами данных. Данный способ упаковки булевых значений применим в любом коде.
Комментариев нет:
Отправить комментарий