Подтвердить что ты не робот

PostgreSQL: разница между типами "bytea" и "bit differenting"

Типы PostgreSQL bytea и bit varying звучат одинаково:

В документации не указывается максимальный размер. Это 1GB, как character varying?

У меня есть два отдельных варианта использования, как по таблице с миллионами строк:

Хранение хешей MD5

Это будет bytea длиной 16 байт или bit(128). Он будет использоваться для:

  • Дедупликация: интенсивное использование GROUP BY, с индексом, который я предполагаю.
  • Запрос с помощью WHERE md5 = только для точных совпадений.
  • Отображение в виде шестнадцатеричной строки для использования человеком.

Сохранение произвольных двоичных данных

Строки двоичных данных различной длины до 4 КБ для:

  • Побитовые операции для поиска строк, соответствующих определенной маске. Пример в конце этого сообщения.
  • Извлечение некоторых байтов, например, получение целочисленного значения байта 14 в моей строке.
  • Некоторая дедупликация.

Рабочий пример для побитовой операции, используя bit varying. Маска X'00FF00 ', и она возвращает только строку X'AAAAAA'. Я сократил строки для примера, но это было бы на всю длину, до 4 КБ. Можно ли сделать что-то подобное с bytea?

CREATE TABLE test1 (mystring bit varying);
INSERT INTO test1 VALUES (X'AAAAAA'), (X'ABCABC');
SELECT * FROM test1 WHERE mystring & X'00FF00' = X'00AA00';

Какой из bytea и bit varying более подходит?

Я видел, что тип UUID создан для хранения ровно 16 байт, было бы ли это преимуществом для хранения MD5?

4b9b3361

Ответ 1

В общем случае, если вы не используете побитовые операции, вы должны использовать bytea.

Я храню большие значения в bytea, а затем конвертирует подстроки в bit varying для поразрядных операций, где это возможно, главным образом потому, что клиенты понимают bytea гораздо более последовательно, чем bit varying, а формат ввода/вывода более компактен.

Значения MD5 должны храниться как bytea. Побитовые операции над ними не имеют никакого смысла, и вы обычно хотите получить их как двоичные.

Я думаю, что bit varying действительно имеет два применения:

  • Сохранение полей флагов, которые являются буквально битными строками; и
  • В качестве промежуточного типа данных для внутренних вычислений

Для почти всего остального используйте bytea.

Там ничего не мешает вам хранить бит 4 бит, если это то, что это такое.

Ответ 2

  • Максимальная длина bytea составляет 1 ГБ. [1]
  • Для побитового использования используйте bit varying (объяснение см. ниже)
  • Для хранения хеша MD5 используйте bytea. Это займет меньше места, чем bit varying
  • Преимущества использования UUID - это алгоритм UUID, который гарантирует вашу уникальность не только в вашей таблице, но также в вашей базе данных или даже в вашей базе данных (даже если вы создаете UUID в своем приложении). Я думаю, что если вы используете UUID без тире, это будет более эффективно для хранения, сравнения и сортировки в UUID (сравнение между bytea и UUID см. Ниже).

Для побитовой операции используйте bit varying

Если вы относитесь к хранению: bit varying занимает больше памяти, чем bytea. Если вы в порядке, попробуйте сравнить функцию, которую они предлагают:

бит изменяется против bytea

До сих пор я вижу, что bit varying будет более подходящим для выполнения побитовой операции, хотя bytea является общепринятым способом хранения произвольных данных.

PostgreSQL предлагает один оператор bytea: конкатенация. Вы можете добавить одно значение byte к другому значению bytea, используя оператор конкатенации ||. [1]

Обратите внимание, что вы не можете сравнить два значения bytea, даже для равенства/неравенства. Разумеется, вы можете преобразовать значение bytea в другое значение с помощью CAST() и открыть другие операторы. [1]

Сравнение UUID и bytea

  create table u(uuid uuid primary key, payload character(300));
  create table b( bytea bytea primary key, payload character(300));

  INSERT INTO u                                                  
  SELECT uuid_generate_v4()                                                     
  FROM generate_series(1,1000*1000);

  INSERT INTO b                                                   
  SELECT random_bytea(16)                                                       
  FROM generate_series(1,1000*1000);

  VACUUM ANALYZE u;
  VACUUM ANALYZE b;

  ## Your table size
  SELECT pg_size_pretty(pg_total_relation_size('u'));
  pg_size_pretty 
  ---------------- 
  81 MB

  SELECT pg_size_pretty(pg_total_relation_size('b'));
  pg_size_pretty 
  ---------------- 
  101 MB

  ## Speed comparison
  \timing on

  ## Common select
  select * from u limit 1000;
  Time: 1.433 ms

  select * from b limit 1000;
  Time: 1.396 ms

  ## Random Select
  SELECT * FROM u OFFSET random()*1000 LIMIT 10000;
  Time: 42.453 ms

  SELECT * FROM b OFFSET random()*1000 LIMIT 10000;
  Time: 10.962 ms

Заключение: я не думаю, что при использовании UUID будет больше пользы, кроме его уникальности и меньшего размера (будет быстрее вставляться)

Примечание. Нет индекса, есть только одно соединение

Некоторые источники:

  • PostgreSQL: "Всеобъемлющее руководство по созданию, программированию и администрированию баз данных PostgreSQL".