Хранение изображений в PostgreSQL

111

Хорошо, я работаю над приложением, которое будет использовать серверную часть Linux под управлением PostgreSQL для передачи изображений в окно Windows с интерфейсом, написанным на C # .NET, хотя интерфейс вряд ли имеет значение. У меня вопрос:

  • Как лучше всего хранить изображения в Postgres?

Изображения имеют размер около 4-6 мегапикселей каждое, а мы храним до 3000. Также стоит отметить: это не веб-приложение, максимум два внешних интерфейса будут обращаться к базе данных одновременно.

акдом
источник

Ответы:

64

Обновление до 2012 года, когда мы видим, что размеры и количество изображений растут и растут во всех приложениях ...

Нам нужно различать «исходное изображение» и «обработанное изображение», например, миниатюру.

Как говорится в ответе Jcoby, есть два варианта, поэтому я рекомендую:

  • используйте blob (Binary Large OBject): для хранения оригинальных изображений за вашим столом. См. Ответ Ивана (нет проблем с резервным копированием больших двоичных объектов!), Дополнительные поставляемые модули PostgreSQL , инструкции и т. Д.

  • использовать отдельную базу данных с DBlink : для оригинального хранилища изображений в другой (унифицированной / специализированной) базе данных. В этом случае я предпочитаю bytea , но blob примерно такой же. Разделение базы данных - лучший способ для «единого веб-сервиса изображений».

  • используйте bytea (BYTE Array): для кэширования миниатюрных изображений. Кэшируйте маленькие изображения, чтобы быстро отправить их в веб-браузер (чтобы избежать проблем с рендерингом) и уменьшить обработку на сервере. Кэшировать также важные метаданные, такие как ширина и высота. Кэширование базы данных - самый простой способ, но проверьте свои потребности и конфигурации сервера (например, модули Apache): может быть лучше хранить эскизы в файловой системе , сравните производительность. Помните, что это (унифицированный) веб-сервис, который затем может храниться в отдельной базе данных (без резервных копий), обслуживая множество таблиц. См. Также руководство по типам двоичных данных PostgreSQL , тесты с байтовым столбцом и т. Д.

ПРИМЕЧАНИЕ 1. Сегодня использование «двойных решений» (база данных + файловая система) устарело (!). Использование «только базы данных» вместо двойного дает много преимуществ. PostgreSQL имеет сопоставимую производительность и хорошие инструменты для экспорта / импорта / ввода / вывода.

ПРИМЕЧАНИЕ 2: помните, что PostgreSQL имеет только bytea , а не имеет BLOB Oracle по умолчанию : «Стандарт SQL определяет (...) BLOB. Формат ввода отличается от bytea, но предоставляемые функции и операторы в основном такие же», Руководство .


РЕДАКТИРОВАТЬ 2014 : Я не изменил исходный текст выше сегодня (мой ответ был 22 апреля 2012 г., теперь с 14 голосами), я открываю ответ на ваши изменения (см. «Режим Wiki», вы можете редактировать!), Для корректуры и для обновлений .
Вопрос стабильный (ответ @Ivans '08 с 19 голосами), помогите, пожалуйста, улучшить этот текст.

Питер Краусс
источник
2
Какова ссылка на «... использование« двойных решений »(база данных + файловая система) устарело ...»?
dangel
Некоторые новости 2019 года! С 2018 года PostgREST поддерживает прямой вывод байта в Интернет. Посмотрите эту простую конфигурацию NGINX, чтобы использовать ее. См. Руководство PostgREST по двоичному выводу
Питер Краусс
52

Ответ Re jcoby:

bytea, являющийся "нормальным" столбцом, также означает, что значение полностью считывается в память, когда вы его извлекаете. Blobs, напротив, можно передавать в стандартный вывод. Это помогает уменьшить объем памяти, занимаемой сервером. Особенно при хранении изображений размером 4-6 Мпикс.

Нет проблем с резервным копированием больших двоичных объектов. pg_dump предоставляет опцию "-b" для включения больших объектов в резервную копию.

Итак, я предпочитаю использовать pg_lo_ *, как вы можете догадаться.

Ответ Криса Эриксона:

Скажу наоборот :). Если изображения - не единственные данные, которые вы храните, не храните их в файловой системе, если в этом нет крайней необходимости. Это такое преимущество - всегда быть уверенным в согласованности данных и иметь данные «в одном куске» (БД). Кстати, PostgreSQL отлично подходит для сохранения согласованности.

Однако, правда, реальность часто слишком требовательна к производительности ;-) и заставляет вас обслуживать двоичные файлы из файловой системы. Но даже в этом случае я склонен использовать БД в качестве «главного» хранилища для двоичных файлов, со всеми другими связями, последовательно связанными, обеспечивая при этом некоторый механизм кэширования на основе файловой системы для оптимизации производительности.

Иван Кречетов
источник
15
Как вы думаете, по прошествии 10 лет ваши баллы все еще в силе? Какие-нибудь обновления с тех пор?
leventunver
3
@leventunver Нет, баллов не удерживать. Например, первое о том, BYTEAчто это «нормальный» столбец. Postgres уже много лет поддерживает потоковую передачу в / из BYTEAстолбцов, что означает, что вам не нужно сохранять содержимое в памяти перед сохранением его в базе данных.
oligofren
29

В базе есть два варианта:

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

В прошлом я с большим успехом использовал столбцы bytea для хранения более 10 ГБ изображений с тысячами строк. Функциональность PG TOAST в значительной степени сводит на нет все преимущества blob-объектов. Вам нужно будет включить столбцы метаданных в любом случае для имени файла, типа содержимого, размеров и т. Д.

Jcoby
источник
1
10 ГБ - это не так много :-( Я ищу решение для
ТБ
2
@ValentinHeinitz Для TB ванильный Postgres борется даже с небольшими текстовыми столбцами.
sudo
23

Быстрое обновление до середины 2015 года:

Вы можете использовать интерфейс внешних данных Postgres , чтобы хранить файлы в более подходящей базе данных. Например, поместите файлы в GridFS, которая является частью MongoDB. Затем используйте https://github.com/EnterpriseDB/mongo_fdw, чтобы получить к нему доступ в Postgres.

Это имеет преимущества, заключающиеся в том, что вы можете получать доступ / читать / писать / создавать резервные копии в Postrgres и MongoDB, в зависимости от того, что дает вам большую гибкость.

Также существуют обёртки сторонних данных для файловых систем: https://wiki.postgresql.org/wiki/Foreign_data_wrappers#File_Wrappers

В качестве примера вы можете использовать это: https://multicorn.readthedocs.org/en/latest/foreign-data-wrappers/fsfdw.html (см. Здесь краткий пример использования)

Это дает вам преимущество согласованности (все связанные файлы определенно есть) и всех других ACID, в то время как они все еще находятся в фактической файловой системе, что означает, что вы можете использовать любую файловую систему, которую хотите, и веб-сервер может обслуживать их напрямую ( Кэширование ОС тоже применяется).

Kenyakorn Ketsombut
источник
1
Спасибо .. Предоставляют ли обёртки сторонних данных (file_fdw) доступ на запись для изображений? Я хочу хранить изображения в файловой системе, а ее метаданные - в Postgresql, но я также должен поддерживать согласованность. У вас есть подробное решение? Есть ли другие расширения? Multicorn нужен питон, и я бы предпочел обойтись без Python ..
Джей Хатвани,
1
Да, у них есть доступ на запись. Они полностью согласованы в обоих направлениях. И нет, я не знаю равного решения, которое могло бы сделать это без Python.
Kenyakorn Ketsombut
18

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

Оригинал

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

//linuxserver/images/imagexxx.jpg

тогда, возможно, вы сможете быстро настроить веб-сервер и сохранить URL-адреса в базе данных (а также локальный путь). В то время как базы данных могут обрабатывать большие объекты и 3000 изображений (4-6 мегапикселей, при условии 500 КБ изображения) 1,5 гигабайта - это не так уж много места, файловые системы гораздо лучше предназначены для хранения больших файлов, чем база данных.

Крис Эриксон
источник
15
Но вы должны придумать способ распределить файлы по нескольким каталогам. Файловые системы не так хороши для хранения миллионов файлов в одном каталоге (на самом деле десять тысяч - уже проблема)
a_horse_with_no_name 03
1
Не отвечает на исходный вопрос. Я лично хочу хранить изображения в Postgres только потому, что мне нужен SQL в качестве уровня абстракции, а также я не хочу управлять файлами в моей файловой системе ext4.
sudo
Я в противоречии, это не ответ на вопрос, но я поддержал его, потому что это лучший ответ, чем ответ на вопрос.
Эндрю Карр
6

Попробуйте это . Я использую двоичный формат больших объектов (LOB) для хранения сгенерированных PDF-документов, некоторые из которых имеют размер 10+ МБ, в базе данных, и он отлично работает.

Майк Риделл
источник
2

Если ваши изображения маленькие, подумайте о том, чтобы сохранить их как base64 в текстовом поле.

Причина в том, что в то время как base64 имеет накладные расходы в 33%, сжатие в основном исчезает. (См. Каковы накладные расходы места при кодировании Base64? ) Ваша база данных будет больше, но пакеты, которые ваш веб-сервер отправляет клиенту, не будут. В html вы можете встроить base64 в тег <img src = "">, что, возможно, может упростить ваше приложение, поскольку вам не нужно будет обслуживать изображения как двоичные в отдельной выборке браузера. Обработка изображений как текста также упрощает ситуацию, когда вам нужно отправлять / получать json, который не очень хорошо обрабатывает двоичные файлы.

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

Это определенно правильный способ работы с эскизами.

(Изображения OP не маленькие, так что это не ответ на его вопрос.)

ccleve
источник