Индекс для сравнения битов в postgreSQL (и других базах данных)

Можно ли ускорить поиск, как показано ниже, с помощью индекса flags, где 5 может быть любым числом?

select * from user where flags & 5 > 0

flags — это целочисленный столбец, и идея этого заключается в том, чтобы хранить различные логические атрибуты в одном столбце. Итак, для этого примера это может быть:

flags bit | 1        | 2      | 4                     | 8        | ...
meaning   | is admin | banned | password needs change | whatever | ...

Таким образом, пользователь, являющийся администратором и чей пароль необходимо изменить, может быть найден с помощью приведенного выше оператора select (даже если у него также установлены другие флаги).

Для postgreSQL я мог бы добавить такой индекс выражения для приведенного выше запроса:

create index index_name on user ((flags & 5 > 0))

Но тогда мне пришлось бы создавать индекс для каждой комбинации флагов, потому что указанный выше индекс работает только для значения flags & 5.

Так есть ли индекс для ускорения flags & any_number > 0?

Я знаю, что мог бы использовать разные логические столбцы для каждого флага (мне кажется неудобным, если у меня > 50 флагов) или битовый тип данных postgreSQL (для которого, как я полагаю, существует тип индекса), но меня особенно интересует, есть ли способ получить индекс для приведенного выше варианта использования в целочисленном столбце.


person Markus    schedule 19.11.2015    source источник


Ответы (1)


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

Вероятно, вы могли бы индексировать выражение:

create index index_my_table_is_admin
on my_table (case flags & 5 when 0 then false else true end)

А затем запрос:

select ...
from   ...
where  (case flags & 5 when 0 then false else true end) = 't';

Но я был бы склонен создать представление:

create view ...
as
select ...
       (case flags & 5 when 0 then false else true end) is_admin
       ...
from   my_table;

Думаю, это интересное интеллектуальное упражнение, но я бы просто использовал набор логических значений.

person David Aldridge    schedule 19.11.2015
comment
Спасибо за Ваш ответ. Я думаю, что способ индексации в postgreSQL может быть create index index_name on user ((flags & 5 > 0)) - или я ошибаюсь? Тогда выбор может быть просто таким, как в моем вопросе (нет необходимости в case, более простой синтаксис). - person Markus; 21.11.2015