PostgreSQL'de Görüntüleri Saklama


111

Pekala, bu yüzden, C # .NET ile yazılmış ön uçlu bir Windows kutusuna resim sunmak için PostgreSQL çalıştıran bir Linux arka uç kullanacak bir uygulama üzerinde çalışıyorum, ancak ön uç pek de önemli değil. Sorum şu:

  • Postgres'te resim depolamanın en iyi yolu nedir?

Görüntüler her biri yaklaşık 4-6 megapikseldir ve 3000'den fazla depolama yapıyoruz. Ayrıca şunu da belirtmek iyi olabilir: bu bir web uygulaması değil, veritabanına aynı anda erişen en fazla iki ön uç olacaktır.

Yanıtlar:


64

Tüm uygulamalarda görüntü boyutlarının ve görüntü sayısının büyüdüğünü ve büyüdüğünü gördüğümüzde 2012'ye güncelleme ...

Küçük resim gibi, "orijinal görüntü" ile "işlenmiş görüntü" arasında bir ayrım yapmamız gerekir.

Jcoby'nin cevabının dediği gibi, iki seçenek var, o zaman tavsiye ederim:

  • kullanmak damla masada, orijinal resim mağaza için: (ikili geniş OBject). Ivan'ın cevabına bakın (blobları yedeklemede sorun yok!), PostgreSQL ek sağlanan modüller , Nasıl yapılır vb.

  • DBlink ile ayrı bir veritabanı kullanın : orijinal görüntü deposu için, başka bir (birleştirilmiş / özelleştirilmiş) veritabanında. Bu durumda bayt'ı tercih ederim , ancak blob aynıdır. Veritabanını ayırmak, "birleşik görüntü web hizmeti" için en iyi yoldur.

  • Kullanım bytea (BYTE Dizisi): Bir görüntü Küçük resim önbelleğe alma için. Küçük resimleri önbelleğe alarak web tarayıcısına hızlı bir şekilde gönderin (oluşturma sorunlarını önlemek için) ve sunucu işlemlerini azaltın. Ayrıca genişlik ve yükseklik gibi önemli meta verileri de önbelleğe alın. Veritabanı önbelleğe alma en kolay yoldur, ancak ihtiyaçlarınızı ve sunucu yapılandırmalarınızı kontrol edin (ör. Apache modülleri): küçük resimleri dosya sisteminde depolamak daha iyi olabilir, performansları karşılaştırın. Bunun (birleşik) bir web hizmeti olduğunu, daha sonra birçok tabloya hizmet veren ayrı bir veritabanında (yedeksiz) depolanabileceğini unutmayın. Ayrıca bkz. PostgreSQL ikili veri türleri kılavuzu , bayt sütunu ile testler vb.

NOT1: bugün "ikili çözümlerin" (veritabanı + dosya sistemi) kullanımı kullanımdan kaldırılmıştır (!). İkili yerine "yalnızca veritabanı" kullanmanın birçok avantajı vardır. PostgreSQL, dışa aktarma / içe aktarma / giriş / çıkış için karşılaştırılabilir performansa ve iyi araçlara sahiptir.

NOT2: PostgreSQL sadece var olduğunu hatırlamak bytea türünde bir değer , varsayılan bir Oracle'ın yok BLOB : "SQL tanımlamış (...) BLOB giriş formatı bytea farklıdır, ancak sağlanan işlevler ve işleçler çoğunlukla aynıdır.", Manuel .


DÜZENLEME 2014 : Bugün yukarıdaki orijinal metni değiştirmedim (cevabım 22 Nisan 2012 idi, şimdi 14 oyla), düzeltmelerinizin yanıtını açıyorum ("Wiki modu" na bakın, düzenleyebilirsiniz!) ve güncellemeler için .
Soru kararlı (@ Ivans'ın '08 yanıtı 19 oyla), lütfen bu metni geliştirmeye yardımcı olun.


2
"..." ikili çözümlerin "(veritabanı + dosya sistemi) kullanımı kullanımdan kaldırıldı ..." için referans nedir?
dangel

Bazı 2019 haberleri! 2018 yılından bu yana PostgREST doğrudan çıkışını destekler bytea web'e. Kullanmak için bu NGINX basit yapılandırmasına bakın . İkili çıktı ile ilgili PostgREST Kılavuzu'na
Peter Krauss

52

Re jcoby'nin cevabı:

baytın "normal" bir sütun olması, değerin siz onu getirdiğinizde tamamen belleğe okunması anlamına da gelir. Bloblar, aksine, standart çıktıya aktarabilirsiniz. Bu, sunucu bellek ayak izini azaltmaya yardımcı olur. Özellikle 4-6 MPix görüntü depoladığınızda.

Blobları yedeklemede sorun yok. pg_dump, büyük nesneleri yedeklemeye dahil etmek için "-b" seçeneği sağlar.

Bu yüzden, tahmin edersiniz ki, pg_lo_ * kullanmayı tercih ederim.

Tekrar Kris Erickson'ın cevabı:

Tersini söyleyebilirim :). Sakladığınız tek veri resimler olmadığında, kesinlikle mecbur kalmadıkça bunları dosya sisteminde saklamayın. Veri tutarlılığınızdan her zaman emin olmak ve verileri "tek parça halinde" (DB) bulundurmak çok büyük bir avantajdır. BTW, PostgreSQL tutarlılığı korumada harika.

Bununla birlikte, doğru, gerçeklik çoğu zaman çok fazla performans gerektirir ;-) ve sizi dosya sisteminden ikili dosyalar sunmaya zorlar. Ancak o zaman bile DB'yi ikili dosyalar için "ana" depolama olarak kullanma eğilimindeyim, diğer tüm ilişkiler tutarlı bir şekilde bağlantılıyken, performans optimizasyonu için bazı dosya sistemi tabanlı önbelleğe alma mekanizması sağlar.


15
10 yıldan sonra puanlarınızın hala geçerli olduğunu düşünüyor musunuz? O zamandan beri herhangi bir güncelleme var mı?
leventunver

3
@leventunver Hayır, tutulmaması gereken noktalar. Örneğin BYTEA"normal" bir sütun olmakla ilgili ilki . Postgres, uzun yıllardır sütunlara / sütunlardan akışı desteklemiştir BYTEA, bu da içeriği db'ye kaydetmeden önce bellekte saklamanıza gerek olmadığı anlamına gelir.
oligofren

29

Veritabanında iki seçenek vardır:

  • bytea. Verileri bir yedeğin parçası olarak dışa aktarılan bir sütunda depolar. Kaydetmek ve geri almak için standart veritabanı işlevlerini kullanır. İhtiyaçlarınız için tavsiye edilir.
  • Lekeler. Normalde bir yedeklemenin parçası olarak dışa aktarılmaz, verileri harici olarak depolar. Kaydetmek ve geri almak için özel veritabanı işlevleri gerektirir.

Geçmişte binlerce satır içeren 10+ gb görüntü depolayarak bayt sütunlarını büyük bir başarıyla kullandım. PG'nin TOAST işlevi, blobların sahip olduğu herhangi bir avantajı hemen hemen yok sayar. Her iki durumda da dosya adı, içerik türü, boyutlar vb. İçin meta veri sütunlarını eklemeniz gerekir.


1
10GB çok fazla değil :-(
TB

2
@ValentinHeinitz TB'ler için vanilya Postgres, daha küçük metin sütunlarıyla bile mücadele eder.
sudo

23

2015 ortasına hızlı güncelleme:

Dosyaları daha uygun bir veritabanında saklamak için Postgres Yabancı Veri arayüzünü kullanabilirsiniz . Örneğin, dosyaları MongoDB'nin parçası olan bir GridFS'ye koyun. Ardından , Postgres'te erişmek için https://github.com/EnterpriseDB/mongo_fdw kullanın.

Bunun avantajları, size neyin daha fazla esneklik sağladığına bağlı olarak Postrgres ve MongoDB'de erişebilir / okuyabilir / yazabilir / yedekleyebilirsiniz.

Dosya sistemleri için yabancı veri sarmalayıcılar da vardır: https://wiki.postgresql.org/wiki/Foreign_data_wrappers#File_Wrappers

Örnek olarak şunu kullanabilirsiniz: https://multicorn.readthedocs.org/en/latest/foreign-data-wrappers/fsfdw.html (kısa kullanım örneği için buraya bakın)

Bu size tutarlılık (tüm bağlantılı dosyalar kesinlikle oradadır) ve diğer tüm ACID'lerin avantajını sağlarken, gerçek dosya sisteminde hala varken, bu da istediğiniz herhangi bir dosya sistemini kullanabileceğiniz ve web sunucusunun bunları doğrudan sunabileceği anlamına gelir ( İşletim sistemi önbelleğe alma da geçerlidir).


1
Teşekkürler .. Yabancı veri sarmalayıcılar (file_fdw) resimler için yazma erişimi sağlıyor mu? Görüntüleri bir FileSystem'e ve meta verilerini Postgresql'de depolamak istiyorum, ancak tutarlılığı da korumam gerekiyor. Ayrıntılı bir çözümünüz var mı? Kullanılabilir başka bir uzantı var mı? Multicorn'un python'a ihtiyacı var ve ben Python kullanmadan yapmayı tercih ederim ..
Jay Khatwani

1
Evet, yazma erişimine sahipler. Her iki yönde de tamamen tutarlıdırlar. Ve hayır, bunu python olmadan yapan eşit bir çözüm bilmiyorum.
Kenyakorn Ketsombut

18

10 yıl sonraki güncelleme 2008'de, üzerinde bir veritabanını çalıştıracağınız sabit diskler, dosyaları depolayacağınız disklerden çok daha farklı özelliklere ve çok daha yüksek maliyete sahip olacaktır. Bu günlerde, 10 yıl önce var olmayan dosyaları depolamak için çok daha iyi çözümler var ve bu tavsiyeyi iptal edip okuyuculara bu konudaki diğer cevaplardan bazılarına bakmalarını tavsiye ediyorum.

orijinal

Kesinlikle mecbur kalmadıkça veritabanındaki görüntüleri saklamayın. Bunun bir web uygulaması olmadığını anlıyorum, ancak paylaşılan bir dosya konumu yoksa, dosyanın konumunu veritabanına kaydetmeyi işaret edebilirsiniz.

//linuxserver/images/imagexxx.jpg

o zaman belki hızlı bir şekilde bir web sunucusu kurabilir ve web url'lerini veritabanında (ve yerel yolda) depolayabilirsiniz. Veritabanları LOB'ları ve 3000 görüntüyü işleyebilirken (4-6 Megapiksel, bir görüntü 500K olduğu varsayılırsa) 1.5 Gigs çok fazla alan değildir dosya sistemleri, büyük dosyaları depolamak için bir veritabanından çok daha iyi tasarlanmıştır.


15
Ancak, dosyaları birkaç dizine dağıtmanın bir yolunu bulmalısınız. Dosya sistemleri, milyonlarca dosyayı tek bir dizinde depolamakta o kadar iyi değil (aslında on binler zaten bir sorundur)
a_horse_with_no_name

1
Orijinal soruyu cevaplamıyor. Kişisel olarak resimleri Postgres'te saklamak istiyorum çünkü SQL'i soyutlama katmanım olarak istiyor ve ext4 dosya sistemimdeki dosyaları yönetmek istemiyorum.
sudo

Kafam karıştı, bu soruya cevap vermiyor, ama ek oy verdim, çünkü bu soruya verilen cevaptan daha iyi bir cevap.
Andrew Carr

6

Deneyin bu . Bazıları 10+ MB boyutunda olan oluşturulmuş PDF belgelerini bir veritabanında depolamak için Büyük Nesne İkili (LOB) biçimini kullanıyorum ve harika bir şekilde çalıştı.


2

Resimleriniz küçükse, bunları düz metin alanında base64 olarak depolamayı düşünün.

Bunun nedeni, base64'ün% 33'lük bir ek yüke sahip olmasına karşın, sıkıştırma çoğunlukla ortadan kalkıyor. (Bkz . Base64 kodlamasının alan ek yükü nedir? ) Veritabanınız daha büyük olacaktır, ancak web sunucunuzun istemciye gönderdiği paketler olmayacaktır. Html'de, base64'ü bir <img src = ""> etiketinde satır içi yapabilirsiniz, bu da muhtemelen uygulamanızı basitleştirebilir, çünkü görüntüleri ayrı bir tarayıcı getirmesinde ikili olarak sunmak zorunda kalmayacaksınız. Görüntüleri metin olarak kullanmak, json göndermeniz / almanız gerektiğinde işleri de basitleştirir, bu da ikiliyi çok iyi yönetmez.

Evet, ikiliyi veritabanında saklayabileceğinizi ve veritabanına girip çıkarken metne / metne dönüştürebileceğinizi anlıyorum, ancak bazen ORM'ler bunu zorlaştırıyor. Diğer tüm alanlarınız gibi onu düz metin olarak ele almak daha basit olabilir.

Küçük resimleri işlemenin kesinlikle doğru yolu budur.

(OP'nin görüntüleri küçük değil, bu yüzden bu onun sorusuna gerçekten bir cevap değil.)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.