Menyimpan Gambar di PostgreSQL


111

Baiklah, jadi saya sedang mengerjakan aplikasi yang akan menggunakan back-end Linux yang menjalankan PostgreSQL untuk menyajikan gambar ke kotak Windows dengan ujung depan tertulis dalam C # .NET, meskipun front-end seharusnya tidak menjadi masalah. Pertanyaanku adalah:

  • Apa cara terbaik untuk menangani penyimpanan gambar di Postgres?

Gambar masing-masing berukuran sekitar 4-6 megapiksel, dan kami menyimpan lebih dari 3000. Mungkin juga baik untuk dicatat: ini bukan aplikasi web, paling banyak akan ada sekitar dua ujung depan yang mengakses database sekaligus.

Jawaban:


64

Memperbarui ke 2012, ketika kami melihat bahwa ukuran gambar, dan jumlah gambar, tumbuh dan berkembang, di semua aplikasi ...

Kami membutuhkan beberapa perbedaan antara "gambar asli" dan "gambar olahan", seperti gambar mini.

Seperti jawaban Jcoby, ada dua opsi, maka, saya merekomendasikan:

  • gunakan blob (Binary Large OBject): untuk menyimpan gambar asli, di meja Anda. Lihat jawaban Ivan (tidak ada masalah dengan mencadangkan gumpalan!), Modul tambahan yang disediakan PostgreSQL , How-tos, dll.

  • gunakan database terpisah dengan DBlink : untuk penyimpanan gambar asli, di database lain (terpadu / khusus). Dalam kasus ini, saya lebih suka bytea , tetapi blob hampir sama. Memisahkan database adalah cara terbaik untuk "layanan web gambar terpadu".

  • gunakan bytea (BYTE Array): untuk menyimpan gambar thumbnail. Cache gambar kecil untuk mengirimkannya dengan cepat ke browser web (untuk menghindari masalah rendering) dan mengurangi pemrosesan server. Cache juga metadata penting, seperti lebar dan tinggi. Caching database adalah cara termudah, tetapi periksa kebutuhan Anda dan konfigurasi server (mis. Modul Apache): menyimpan thumbnail di sistem file mungkin lebih baik, bandingkan performanya. Ingatlah bahwa ini adalah layanan web (terpadu), kemudian dapat disimpan di database terpisah (tanpa cadangan), melayani banyak tabel. Lihat juga manual tipe data biner PostgreSQL , tes dengan kolom bytea , dll.

CATATAN1: saat ini penggunaan "solusi ganda" (database + filesystem) tidak digunakan lagi (!). Ada banyak keuntungan menggunakan "hanya database", bukan dual. PostgreSQL memiliki kinerja yang sebanding dan alat yang bagus untuk ekspor / impor / input / output.

CATATAN2: ingat bahwa PostgreSQL hanya memiliki bytea , tidak memiliki BLOB Oracle default : "Standar SQL mendefinisikan (...) BLOB. Format input berbeda dari bytea, tetapi fungsi dan operator yang disediakan sebagian besar sama", Manual .


EDIT 2014 : Saya belum mengubah teks asli di atas hari ini (jawaban saya adalah 22 Apr '12, sekarang dengan 14 suara), saya membuka jawaban untuk perubahan Anda (lihat "mode Wiki", Anda dapat mengedit!), Untuk mengoreksi dan untuk pembaruan .
Pertanyaannya stabil (jawaban '08 @ Ivans dengan 19 suara), tolong, bantu untuk memperbaiki teks ini.


2
Apa referensi untuk "... penggunaan" solusi ganda "(database + filesystem) tidak digunakan lagi ..."?
dangel

Beberapa berita 2019! Sejak 2018 PostgREST mendukung keluaran langsung bytea ke web. Lihat konfigurasi sederhana NGINX ini untuk menggunakannya. Lihat Panduan PostgREST tentang keluaran biner
Peter Krauss

52

Jawaban Re jcoby:

bytea menjadi kolom "normal" juga berarti nilai dibaca seluruhnya ke dalam memori saat Anda mengambilnya. Blob, sebaliknya, Anda dapat melakukan streaming ke stdout. Itu membantu dalam mengurangi jejak memori server. Terutama saat Anda menyimpan gambar 4-6 MPix.

Tidak masalah dengan mencadangkan blob. pg_dump menyediakan opsi "-b" untuk menyertakan objek besar ke dalam cadangan.

Jadi, saya lebih suka menggunakan pg_lo_ *, Anda mungkin menebaknya.

Jawaban Re Kris Erickson:

Saya akan mengatakan sebaliknya :). Jika gambar bukan satu-satunya data yang Anda simpan, jangan menyimpannya di sistem file kecuali Anda benar-benar harus melakukannya. Sungguh menguntungkan untuk selalu yakin tentang konsistensi data Anda, dan memiliki data "dalam satu bagian" (DB). BTW, PostgreSQL sangat bagus dalam menjaga konsistensi.

Namun, sebenarnya, kenyataannya seringkali terlalu menuntut kinerja ;-), dan ini mendorong Anda untuk melayani file biner dari sistem file. Tetapi bahkan kemudian saya cenderung menggunakan DB sebagai penyimpanan "master" untuk binari, dengan semua relasi lainnya secara konsisten terhubung, sambil menyediakan beberapa mekanisme cache berbasis sistem file untuk pengoptimalan kinerja.


14
Setelah 10 tahun, apakah menurut Anda poin Anda masih berlaku? Ada pembaruan sejak itu?
leventunver

3
@leventunver Tidak, poin untuk tidak ditahan. Misalnya yang pertama tentang BYTEAmenjadi kolom "normal". Postgres telah mendukung streaming ke / dari BYTEAkolom selama bertahun-tahun, yang berarti Anda tidak perlu menyimpan konten di memori sebelum menyimpannya di db.
oligofren

29

Di database, ada dua opsi:

  • bytea. Menyimpan data dalam kolom, diekspor sebagai bagian dari cadangan. Menggunakan fungsi database standar untuk menyimpan dan mengambil. Direkomendasikan untuk kebutuhan Anda.
  • gumpalan. Menyimpan data secara eksternal, biasanya tidak diekspor sebagai bagian dari cadangan. Membutuhkan fungsi database khusus untuk menyimpan dan mengambil.

Saya telah menggunakan kolom bytea dengan sukses besar di masa lalu menyimpan 10 + gb gambar dengan ribuan baris. Fungsionalitas PG TOAST cukup banyak meniadakan keuntungan yang dimiliki blob. Anda harus menyertakan kolom metadata dalam kedua kasus untuk nama file, jenis konten, dimensi, dll.


1
10GB tidak banyak :-( Saya sedang mencari solusi TB
Valentin Heinitz

2
@ValentinHeinitz Untuk TB, vanilla Postgres berjuang bahkan dengan kolom teks yang lebih kecil.
sudo

23

Pembaruan cepat hingga pertengahan 2015:

Anda dapat menggunakan antarmuka Data Asing Postgres , untuk menyimpan file dalam database yang lebih sesuai. Misalnya meletakkan file di GridFS yang merupakan bagian dari MongoDB. Kemudian gunakan https://github.com/EnterpriseDB/mongo_fdw untuk mengaksesnya di Postgres.

Itu memiliki kelebihan, Anda dapat mengakses / membaca / menulis / mencadangkannya di Postrgres dan MongoDB, tergantung pada apa yang memberi Anda lebih banyak fleksibilitas.

Ada juga pembungkus data asing untuk sistem file: https://wiki.postgresql.org/wiki/Foreign_data_wrappers#File_Wrappers

Sebagai contoh, Anda dapat menggunakan yang ini: https://multicorn.readthedocs.org/en/latest/foreign-data-wrappers/fsfdw.html (lihat di sini untuk contoh penggunaan singkat)

Itu memberi Anda keuntungan dari konsistensi (semua file tertaut pasti ada) dan semua ACID lainnya, sementara masih ada di sistem file yang sebenarnya, yang berarti Anda dapat menggunakan sistem file apa pun yang Anda inginkan dan server web dapat melayani mereka secara langsung ( Caching OS juga berlaku).


1
Terima kasih .. Apakah pembungkus data asing (file_fdw) menyediakan akses tulis untuk gambar? Saya ingin menyimpan gambar ke FileSystem dan metadatanya di Postgresql, tetapi saya juga harus menjaga konsistensi. Apakah Anda memiliki solusi terperinci? Apakah ada ekstensi lain yang tersedia? Multicorn membutuhkan python dan saya lebih suka melakukannya tanpa menggunakan Python ..
Jay Khatwani

1
Ya, mereka memiliki akses tulis. Mereka sepenuhnya konsisten dari / di kedua arah. Dan tidak, saya tidak tahu solusi yang sama yang melakukan ini tanpa python.
Kenyakorn Ketsombut

18

Perbarui dari 10 tahun kemudian Pada tahun 2008 hard drive tempat Anda menjalankan database akan memiliki karakteristik yang jauh berbeda dan biaya yang jauh lebih tinggi daripada disk tempat Anda menyimpan file. Saat ini ada solusi yang jauh lebih baik untuk menyimpan file yang tidak ada 10 tahun yang lalu dan saya akan mencabut saran ini dan menyarankan pembaca untuk melihat beberapa jawaban lain di utas ini.

Asli

Jangan simpan dalam gambar di database kecuali Anda benar-benar harus melakukannya. Saya mengerti bahwa ini bukan aplikasi web, tetapi jika tidak ada lokasi file bersama yang dapat Anda arahkan untuk menyimpan lokasi file di database.

//linuxserver/images/imagexxx.jpg

maka mungkin Anda dapat dengan cepat menyiapkan server web dan menyimpan url web di database (serta jalur lokal). Sementara database dapat menangani LOB dan 3000 gambar (4-6 Megapiksel, dengan asumsi gambar 500K) 1.5 Gigs bukanlah banyak ruang sistem file jauh lebih baik dirancang untuk menyimpan file besar daripada database.


15
Tetapi Anda harus menemukan cara untuk mendistribusikan file melalui beberapa direktori.
Sistem

1
Tidak menjawab pertanyaan awal. Saya pribadi ingin menyimpan gambar di Postgres hanya karena saya ingin SQL sebagai lapisan abstraksi saya dan juga tidak ingin mengelola file di sistem file ext4 saya.
sudo

Saya berkonflik, ini tidak menjawab pertanyaan, tetapi saya memilihnya, karena ini adalah jawaban yang lebih baik daripada jawaban atas pertanyaan.
Andrew Carr

6

Coba ini . Saya telah menggunakan format Large Object Binary (LOB) untuk menyimpan dokumen PDF yang dihasilkan, beberapa di antaranya berukuran 10+ MB, dalam database dan bekerja dengan sangat baik.


2

Jika gambar Anda kecil, pertimbangkan untuk menyimpannya sebagai base64 dalam bidang teks biasa.

Alasannya adalah bahwa sementara base64 memiliki overhead 33%, dengan kompresi yang sebagian besar hilang. (Lihat Berapa overhead ruang pengkodean Base64? ) Database Anda akan lebih besar, tetapi paket yang dikirim server web Anda ke klien tidak. Di html, Anda dapat menyebariskan base64 dalam tag <img src = "">, yang mungkin dapat menyederhanakan aplikasi Anda karena Anda tidak perlu menyajikan gambar sebagai biner dalam pengambilan browser terpisah. Menangani gambar sebagai teks juga menyederhanakan hal-hal ketika Anda harus mengirim / menerima json, yang tidak menangani biner dengan baik.

Ya, saya mengerti Anda dapat menyimpan biner dalam database dan mengubahnya menjadi / dari teks saat masuk dan keluar dari database, tapi terkadang ORM membuatnya merepotkan. Ini bisa lebih sederhana untuk memperlakukannya sebagai teks lurus seperti semua bidang Anda yang lain.

Ini jelas merupakan cara yang tepat untuk menangani gambar mini.

(Gambar OP tidak kecil, jadi ini bukan jawaban untuk pertanyaannya.)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.