Должен ли я использовать битовую строку PostgreSQL?


18

Недавно я узнал о bit stringтипе данных, и мне довольно любопытно:

  1. Внизу этой страницы документа есть предложение:

    ... плюс 5 или 8 байтов в зависимости от длины строки

  2. Как обрабатываются битовые строки на других языках, таких как PHP, Java, C #, C ++ и т. Д., Через драйверы, такие как Npgsql, ODBC и т. Д.

Для вопроса № 1 использование smallint или bigint будет намного более эффективным с точки зрения хранения и, возможно, обеспечит выигрыш в производительности, поскольку целые числа поддерживаются везде. Большинство языков программирования с легкостью обрабатывают битовые операции над целыми числами. Если это так, то какой смысл вводить тип данных битовой строки? Только для случаев, когда требуется большое количество битовых масок? Индексация битового поля может быть? Меня больше интересует, как выполняется индексация битовых полей в PostgreSQL.

Для # 2, я запутался, более чем любопытно. Например, что если я сохраню битовые маски дня недели в поле bit (7), один бит на день, причем младший бит представляет понедельник. Затем я запрашиваю значение в PHP и C ++. Что я получу? В документации сказано, что у меня будет битовая строка, однако битовую строку я не могу использовать напрямую - как с целыми числами. Тогда в этом случае я должен отказаться от битового поля?

Кто-нибудь может уточнить, почему и когда я должен использовать бит или бит по-разному?



2
Ответ Эрвина на SO великолепен (и если вы не против скопировать его через @Erwin, было бы полезно иметь его здесь), но я бы хотел добавить свою собственную осторожность: в большинстве случаев вы не будете задумываться о сохранении информации в битовых строках в СУБД - использование отдельных логических столбцов в обычном решении независимо от «эффективности» хранилища.
Джек Дуглас

@JackDouglas: я не против скопировать мой ответ. Интересно, хотя: дублирование ответа на сайтах SE - хорошая идея?
Эрвин Брандштеттер,

@ Эрвин Я не понимаю, почему нет - между сайтами есть некоторое совпадение, и они оба должны стоять в одиночестве (например, мы бы не стали - и в любом случае не могли бы - закрыть вопрос здесь как дубликат, если бы был идентичный вопрос по SO). Мы больше фокусируемся на «экспертных» вопросах, но IMO ваш ответ соответствует этой категории в том виде, в каком она есть :)
Джек Дуглас,

@JackDouglas: Ну, имеет смысл. И как я мог не согласиться после похвалы, которую ты проскользнул? ;)
Эрвин Брандштеттер

Ответы:


18

Если у вас есть только несколько переменных, я бы хотел сохранить отдельные booleanстолбцы.

  • Индексирование легко. В частности, индексы по выражениям просты.
  • Условия для запросов и частичной индексации легко пишутся, читаются и имеют смысл.
  • Логический столбец занимает 1 байт. Только для нескольких переменных это занимает меньше всего места.
  • В отличие от других параметров логические столбцы позволяют NULLзначения для отдельных битов, если вам это нужно. Вы всегда можете определить столбцы, NOT NULLесли вы этого не сделаете.

Оптимизация хранилища

Если у вас больше чем полные переменные, но меньше 33, integerстолбец может вам помочь. (Или bigintдля до 64 переменных.)

  • Занимает 4 байта на диске.
  • Очень быстрая индексация для точных совпадений ( =оператор).
  • Обработка отдельных значений может быть медленнее / менее удобной, чем с помощью bit stringили boolean.

С еще большим количеством переменных, или если вы хотите много манипулировать значениями, или если у вас нет больших таблиц и дискового пространства / ОЗУ не проблема, или если вы не уверены, что выбрать, я бы рассмотрел bit(n)илиbit varying(n) .

  • Занимает не менее 5 байтов (или 8 для очень длинных строк) плюс 1 байт для каждой группы из 8 бит (с округлением в большую сторону).
  • Вы можете напрямую использовать функции и операторы битовых строк .

Примеры

Только для 3 битов информации отдельные booleanстолбцы обходятся 3 байтами, integerтребуются 4 байта и bit string6 байтов (5 + 1).

Для 32 бит информации integerвсе еще требуется 4 байта, a bit stringзанимает 9 байтов для того же (5 + 4), а booleanстолбцы занимают 32 байта.

дальнейшее чтение


Да, я согласен с вами. В настоящее время я использую samllint для хранения битовой маски будних дней. Это подходит для случая, эффективность хранения / производительность в целом. Однако, если бы у меня была дополнительная индексация / фильтрация по битовым маскам, она потерпит неудачу из-за низкой производительности.
Джеки Чунг

3

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

Я ожидаю, что на прикладном уровне, если ваш db-драйвер не обработает его через какое-то преобразование типов, вы получите строковое представление и должны это обработать. Так что это может или не может быть полезным в этом качестве.

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

Также обратите внимание, что для более длинных строк двоичной информации имеется большой объектный интерфейс, который позволяет выполнять потоковую передачу и т. Д., И интерфейс bytea, который позволяет более компактное представление строк.

ТЛ; Д-р: Если вам это нужно, вы об этом узнаете. В противном случае сохраните его в разделе «зарезервировано для будущего использования».

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.