Перенести столбец текста/байта PostgreSQL в большой объект?

У меня есть таблица (10 тыс. строк), в которой хранятся большие значения в столбце text. Текущий наибольший размер составляет 417 МБ без сжатия (85 МБ в сжатом виде). Недостатком этой схемы является невозможность потоковой передачи этих значений (например, через JDBC) — все, что использует этот столбец, должно считывать все это в память.

Существуют ли какие-либо инструменты или ярлыки для переноса этого столбца в большие объекты? Минимизация рабочего диска и требуемой памяти.

Я буду использовать lo_compat_privileges, если это что-то изменит.


person OrangeDog    schedule 05.03.2019    source источник
comment
Это обратная миграция на PostgreSQL: с OID на Bytea.   -  person OrangeDog    schedule 05.03.2019


Ответы (1)


Почему бы просто не использовать lo_from_bytea?

Пример:

SELECT 'test'::text::bytea;
   bytea    
------------
 \x74657374
(1 row)

SELECT lo_from_bytea(0, 'test'::text::bytea);
 lo_from_bytea 
---------------
        274052
(1 row)

SELECT lo_get(274052);
   lo_get   
------------
 \x74657374
(1 row)

Итак, чтобы фактически переместить (вам лучше иметь резервную копию) данные из текста в OID, вы можете сделать следующее:

ALTER TABLE mytable ADD COLUMN value_lo OID;
UPDATE mytable SET value_lo = lo_from_bytea(0, value::bytea), value = NULL;
ALTER TABLE mytable DROP COLUMN value;
ALTER TABLE mytable RENAME COLUMN value_lo TO value;

... и, наконец, поскольку PostgreSQL является базой данных MVCC и не сразу удаляет все данные, вы должны очистить все с помощью VACUUM FULL или CLUSTER.

person Ancoron    schedule 05.03.2019
comment
Эээ.. нет. Вы не можете возиться с типом данных в PostgreSQL. Я обновлю ответ, чтобы включить потенциальную процедуру обновления. - person Ancoron; 05.03.2019
comment
Итак, (при условии, что большие объекты также сжаты) мне понадобится вдвое больше текущего табличного пространства. Но понадобится ли этому единственному ОБНОВЛЕНИЮ пространство WAL для всей несжатой таблицы сразу? - person OrangeDog; 05.03.2019
comment
Да, мне нужны транснациональные обновления для отдельных строк этой таблицы. Однако мне не нужно выполнять всю эту миграцию за одну транзакцию. Вот почему я спрашиваю об использовании памяти и диска. У меня нет 500 ГБ оперативной памяти и неограниченного дискового пространства. - person OrangeDog; 05.03.2019
comment
Что ж, с PostgreSQL, работающим в основном с копированием при записи, и с такими большими объектами внутри базы данных, вы должны учитывать довольно много резервной емкости (HDD/SSD) для параллельных операций записи и обслуживания, таких как эти этапы эволюции схемы. Для этого не нужно много оперативной памяти. И вы всегда можете запускать операторы UPDATE небольшими партиями с дополнительным предложением WHERE (даже по одному в начале), чтобы получить представление о производительности и предсказать общее время выполнения. Но извините, преобразование на месте невозможно без дублирования фактических данных. - person Ancoron; 05.03.2019
comment
В: Записывается ли при одном обновлении одна запись WAL? О: Нет, WAL не является журналом выписок, а содержит фактические данные. В нашем случае скорее всего полные данные. В: Содержит ли он полные несжатые данные? A: В зависимости от вашей конфигурации для wal_compression. Вопрос. Сжимается ли большой объект так же, как текстовый столбец, или дополнительное разбиение означает, что TOAST не используется? О: Вот вам все уровни детализации: postgresql.org/docs/current/largeobjects .html - person Ancoron; 05.03.2019
comment
Запускаю тест сейчас. Похоже, что он не использует дополнительную память, но довольно много процессора. Архивирование WAL может быть узким местом, поэтому, вероятно, стоит отключить его (и обязательно делать базовые резервные копии вручную до и после). Также слишком часто (с разницей в 23 секунды) происходит множество контрольных точек, но я понимаю, что это, вероятно, можно игнорировать. - person OrangeDog; 06.03.2019
comment
Несмотря на то, что VACUUM FULL сообщил об отсутствии мертвых строк, использование диска уменьшилось. Результирующий размер увеличился на 30 ГБ по сравнению с предыдущими 52 ГБ. - person OrangeDog; 06.03.2019
comment
на всех уровнях детализации - про сжатие там ничего нет - person OrangeDog; 06.03.2019
comment
Да, потому что большие объекты не сжимаются, поскольку они просто управляют файлами с произвольным двоичным содержимым. Если вам действительно нужно сжать данные, вам нужно предоставить уже сжатые данные при записи в большой объект. Кроме того, чтобы сохранить ввод-вывод WAL и пространство, вы можете временно отключить ведение журнала таблицы с помощью ALTER TABLE <mytable> SET UNLOGGED, но не забудьте потом снова включить его. - person Ancoron; 06.03.2019