Przechowywanie obrazów w PostgreSQL


111

W porządku, więc pracuję nad aplikacją, która będzie korzystała z zaplecza Linuksa z PostgreSQL do wyświetlania obrazów na pudełku z systemem Windows z interfejsem napisanym w C # .NET, chociaż front-end nie powinien mieć większego znaczenia. Moje pytanie brzmi:

  • Jaki jest najlepszy sposób na przechowywanie zdjęć w Postgres?

Obrazy mają około 4-6 megapikseli każdy, a my przechowujemy ponad 3000. Warto również zauważyć: to nie jest aplikacja internetowa, będzie najwyżej około dwóch frontonów uzyskujących dostęp do bazy danych jednocześnie.

Odpowiedzi:


64

Aktualizacja do 2012 r., Kiedy widzimy, że rozmiary i liczba obrazów rosną i rosną we wszystkich aplikacjach ...

Potrzebujemy pewnego rozróżnienia między „oryginalnym obrazem” a „przetworzonym obrazem”, na przykład miniaturą.

Jak mówi odpowiedź Jcoby'ego, są dwie opcje, więc polecam:

  • użyj blob (Binary Large OBject): do oryginalnego magazynu obrazów, przy stole. Zobacz odpowiedź Ivana (nie ma problemu z tworzeniem kopii zapasowych blobów!), Dodatkowe dostarczone moduły PostgreSQL , instrukcje itp.

  • użyj oddzielnej bazy danych z DBlink : dla oryginalnego magazynu obrazów, w innej (zunifikowanej / wyspecjalizowanej) bazie danych. W tym przypadku wolę bajtę , ale blob jest prawie taki sam. Oddzielenie bazy danych to najlepszy sposób na „ujednoliconą usługę sieciową obrazu”.

  • użyj bajtu (BYTE Array): do buforowania obrazów miniatur. Buforuj małe obrazy, aby szybko wysłać je do przeglądarki internetowej (aby uniknąć problemów z renderowaniem) i zmniejszyć przetwarzanie serwera. Buforuj również istotne metadane, takie jak szerokość i wysokość. Buforowanie bazy danych jest najłatwiejszym sposobem, ale sprawdź swoje potrzeby i konfiguracje serwera (np. Moduły Apache): przechowuj miniatury w systemie plików może być lepsze, porównaj wydajność. Pamiętaj, że jest to (ujednolicona) usługa internetowa, a następnie może być przechowywana w oddzielnej bazie danych (bez kopii zapasowych), obsługującej wiele tabel. Zobacz także podręcznik typów danych binarnych PostgreSQL , testy z kolumną bajtową itp.

UWAGA 1: obecnie używanie „podwójnych rozwiązań” (baza danych + system plików) jest przestarzałe (!). Stosowanie „tylko bazy danych” zamiast podwójnej ma wiele zalet. PostgreSQL ma porównywalną wydajność i dobre narzędzia do eksportu / importu / wejścia / wyjścia.

UWAGA2: pamiętaj, że PostgreSQL ma tylko bajty , nie ma domyślnego BLOBa Oracle : "Standard SQL definiuje (...) BLOB. Format wejściowy różni się od bajtu, ale dostarczone funkcje i operatory są w większości takie same", Manual .


EDYCJA 2014 : Nie zmieniłem dzisiaj oryginalnego tekstu powyżej (moja odpowiedź brzmiała 22 kwietnia 2012, teraz z 14 głosami), otwieram odpowiedź na twoje zmiany (zobacz "Tryb Wiki", możesz edytować!), Do korekty i do aktualizacji .
Pytanie jest stabilne (odpowiedź @ Ivans '08 z 19 głosami), pomóżcie ulepszyć ten tekst.


2
Jakie jest odniesienie do "... użycie" podwójnych rozwiązań "(baza danych + system plików) jest przestarzałe ..."?
dangel

Trochę nowości 2019! Od 2018 roku PostgREST obsługuje bezpośrednie wysyłanie bajtów do sieci. Zobacz tę prostą konfigurację NGINX, aby z niej korzystać. Zobacz przewodnik PostgREST dotyczący wyjścia binarnego
Peter Krauss

52

Odpowiedź Re jcoby'ego:

Bajt będący „zwykłą” kolumną oznacza również, że wartość jest w całości odczytywana do pamięci podczas jej pobierania. Natomiast obiekty blob można przesyłać strumieniowo do standardowego wyjścia. Pomaga to zmniejszyć zużycie pamięci serwera. Szczególnie, gdy przechowujesz obrazy o rozdzielczości 4-6 MPix.

Nie ma problemu z tworzeniem kopii zapasowych obiektów blob. pg_dump udostępnia opcję "-b", która umożliwia dołączenie dużych obiektów do kopii zapasowej.

Więc wolę używać pg_lo_ *, możesz się domyślić.

Odpowiedź Re Kris Erickson:

Powiedziałbym odwrotnie :). Jeśli obrazy nie są jedynymi danymi, które przechowujesz, nie przechowuj ich w systemie plików, chyba że jest to absolutnie konieczne. Taką korzyścią jest mieć zawsze pewność co do spójności danych i mieć dane „w jednym kawałku” (DB). BTW, PostgreSQL świetnie zachowuje spójność.

Jednak, prawda, rzeczywistość często wymaga zbyt dużej wydajności ;-) i popycha cię do obsługi plików binarnych z systemu plików. Ale nawet wtedy staram się używać bazy danych jako "głównej" pamięci dla plików binarnych, ze wszystkimi innymi relacjami konsekwentnie połączonymi, zapewniając jednocześnie mechanizm buforowania oparty na systemie plików w celu optymalizacji wydajności.


15
Czy myślisz, że po 10 latach Twoje punkty są nadal ważne? Jakieś aktualizacje od tego czasu?
leventunver

3
@leventunver Nie, punkty, których nie należy trzymać. Na przykład pierwsza o BYTEAbyciu „normalną” kolumną. Postgres od wielu lat obsługuje przesyłanie strumieniowe do / z BYTEAkolumn, co oznacza, że ​​nie musisz przechowywać zawartości w pamięci przed zapisaniem jej w bazie danych.
oligofren

29

W bazie danych są dwie opcje:

  • bajt. Przechowuje dane w kolumnie, eksportowane jako część kopii zapasowej. Używa standardowych funkcji bazy danych do zapisywania i pobierania. Polecane do Twoich potrzeb.
  • plamy. Przechowuje dane na zewnątrz, które normalnie nie są eksportowane jako część kopii zapasowej. Wymaga specjalnych funkcji bazy danych do zapisywania i pobierania.

W przeszłości używałem kolumn bajtowych z dużym powodzeniem, przechowując ponad 10 GB obrazów z tysiącami wierszy. Funkcjonalność TOAST w PG praktycznie neguje wszelkie zalety, jakie mają plamy. W obu przypadkach musisz uwzględnić kolumny metadanych dotyczące nazwy pliku, typu zawartości, wymiarów itp.


1
10 GB to niewiele :-( Szukam rozwiązania TBs
Valentin Heinitz

2
@ValentinHeinitz W przypadku TB, waniliowy Postgres zmaga się nawet z mniejszymi kolumnami tekstu.
sudo

23

Szybka aktualizacja do połowy 2015 r .:

Możesz użyć interfejsu danych obcych Postgres , aby przechowywać pliki w bardziej odpowiedniej bazie danych. Na przykład umieść pliki w GridFS, który jest częścią MongoDB. Następnie użyj https://github.com/EnterpriseDB/mongo_fdw, aby uzyskać do niego dostęp w Postgres.

Ma to zalety, że możesz uzyskać dostęp / odczytać / zapisać / wykonać kopię zapasową w Postrgres i MongoDB, w zależności od tego, co zapewnia większą elastyczność.

Istnieją również obce opakowania danych dla systemów plików: https://wiki.postgresql.org/wiki/Foreign_data_wrappers#File_Wrappers

Jako przykład możesz użyć tego: https://multicorn.readthedocs.org/en/latest/foreign-data-wrappers/fsfdw.html (zobacz tutaj krótki przykład użycia)

Daje to przewagę w postaci spójności (wszystkie połączone pliki na pewno tam są) i wszystkich innych ACID, podczas gdy nadal istnieją w rzeczywistym systemie plików, co oznacza, że ​​możesz używać dowolnego systemu plików, a serwer sieciowy może je obsługiwać bezpośrednio ( Buforowanie systemu operacyjnego ma również zastosowanie).


1
Dzięki ... Czy opakowania danych obcych (file_fdw) zapewniają dostęp do zapisu obrazów? Chcę przechowywać obrazy w systemie plików i jego metadane w Postgresql, ale muszę też zachować spójność. Masz szczegółowe rozwiązanie? Czy jest dostępne inne rozszerzenie? Multicorn potrzebuje Pythona i wolałbym się obejść bez korzystania z Pythona ..
Jay Khatwani

1
Tak, mają prawo do zapisu. Są w pełni spójne w obu kierunkach. I nie, nie znam równego rozwiązania, które robi to bez Pythona.
Kenyakorn Ketsombut

18

Aktualizacja sprzed 10 lat W 2008 r. Dyski twarde, na których będzie można uruchomić bazę danych, będą miały znacznie inne właściwości i znacznie wyższe koszty niż dyski, na których będą przechowywane pliki. W dzisiejszych czasach istnieją znacznie lepsze rozwiązania do przechowywania plików, które nie istniały 10 lat temu, więc odwołałbym tę radę i radziłbym czytelnikom zapoznać się z innymi odpowiedziami w tym wątku.

Oryginalny

Nie przechowuj obrazów w bazie danych, chyba że jest to absolutnie konieczne. Rozumiem, że nie jest to aplikacja internetowa, ale jeśli nie ma udostępnionej lokalizacji pliku, możesz wskazać, aby zapisać lokalizację pliku w bazie danych.

//linuxserver/images/imagexxx.jpg

wtedy możesz szybko skonfigurować serwer sieciowy i przechowywać adresy URL w bazie danych (a także ścieżkę lokalną). Podczas gdy bazy danych mogą obsłużyć LOB i 3000 obrazów (4-6 megapikseli, zakładając 500 KB na obraz) 1,5 gigabajta to niewiele, systemy plików są znacznie lepiej zaprojektowane do przechowywania dużych plików niż baza danych.


15
Ale musisz wymyślić sposób na dystrybucję plików w kilku katalogach. Systemy plików nie są tak dobre, jeśli chodzi o przechowywanie milionów plików w jednym katalogu (w rzeczywistości dziesięć tysięcy to już problem)
a_horse_with_no_name

1
Nie odpowiada na pierwotne pytanie. Osobiście chcę przechowywać obrazy w Postgres tylko dlatego, że chcę SQL jako moją warstwę abstrakcji, a także nie chcę zarządzać plikami w moim systemie plików ext4.
sudo

Jestem skonfliktowany, to nie odpowiada na pytanie, ale zagłosowałem za tym, ponieważ jest to lepsza odpowiedź niż odpowiedź na pytanie.
Andrew Carr,

6

Spróbuj tego . Użyłem formatu Large Object Binary (LOB) do przechowywania wygenerowanych dokumentów PDF, z których niektóre miały rozmiar ponad 10 MB, w bazie danych i działało cudownie.


2

Jeśli Twoje obrazy są małe, rozważ zapisanie ich jako base64 w zwykłym polu tekstowym.

Powodem jest to, że podczas gdy base64 ma narzut na poziomie 33%, przy kompresji, która w większości znika. (Zobacz Jakie jest obciążenie miejsca związane z kodowaniem Base64? ) Twoja baza danych będzie większa, ale pakiety wysyłane przez serwer WWW do klienta nie będą. W html możesz umieścić base64 w tagu <img src = "">, co może uprościć twoją aplikację, ponieważ nie będziesz musiał wyświetlać obrazów jako plików binarnych w osobnym pobieraniu przeglądarki. Obsługa obrazów jako tekstu również upraszcza rzeczy, gdy musisz wysyłać / odbierać json, co nie obsługuje zbyt dobrze plików binarnych.

Tak, rozumiem, że możesz przechowywać plik binarny w bazie danych i konwertować go do / z tekstu podczas wchodzenia i wychodzenia z bazy danych, ale czasami ORMy sprawiają, że jest to kłopotliwe. Może być prostsze traktowanie go jako prostego tekstu, tak jak wszystkie inne pola.

To zdecydowanie właściwy sposób postępowania z miniaturami.

(Obrazy OP nie są małe, więc nie jest to odpowiedź na jego pytanie.)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.