Milyonlarca görüntüyü dosya sisteminde saklamak


79

Çok sayıda imaj üretecek bir projem var. Başlangıç ​​için yaklaşık 1,000,000. Büyük görüntüler değiller, bu yüzden hepsini başlangıçta bir makinede saklayacağım.

Bu görüntüleri etkili bir şekilde saklamak için nasıl bir öneriniz var? (Şu anda NTFS dosya sistemi)

Bir adlandırma şeması düşünüyorum ... başlangıç ​​için tüm resimlerin 1'den yukarıya doğru artan bir adı olacak. Umarım gerekirse bunları daha sonra sıralamama ve farklı klasörlere atmama yardımcı olur.

daha iyi bir adlandırma şeması ne olurdu:

a / b / c / 0 ... z / z / z / 999

veya

a / b / c / 000 ... z / z / z / 999

bunun hakkında bir fikrin var mı?


1
Belirli kullanıcılara bağlı mı yoksa yalnızca genel mi? Herhangi bir şekilde gruplandırılmışlar mı?

sadece genel. Bazı teknik ekipman tarafından oluşturulan görüntülerin bir demet. Onları 1'den 1'e kadar artımlı olarak adlandıracağım.
s.mihai

nasıl kullanılacaklar / erişilecekler? ısmarlama bir uygulama aracılığıyla ya da ne?
güvercin


1
:)) evet ... 1 mil. porno resimler :))
s.mihai

Yanıtlar:


73

Veritabanları yerine normal bir dosya sistemi kullanmanızı öneririm. Dosya sistemini kullanmak bir veritabanından daha kolaydır, dosyalara erişmek için normal araçları kullanabilirsiniz, dosya sistemleri bu tür kullanımlar için tasarlanmıştır. NTFS bir depolama sistemi olarak iyi çalışmalıdır.

Veritabanına asıl yolu saklamayın. Resmin sıra numarasını veritabanına kaydetmek ve sıra numarasından yol oluşturabilecek işleve sahip olmak daha iyidir. Örneğin:

 File path = generatePathFromSequenceNumber(sequenceNumber);

Dizin yapısını nasıl değiştireceğinize karar vermek kolaydır. Belki görüntüleri farklı bir yere taşımanız gerekir, belki de boş yeriniz kalıyor ve resimlerin bir kısmını A ve bazılarını B vb. Disklerde depolamaya başlıyorsunuz. Bir işlevi değiştirmek veritabanındaki yolları değiştirmek yerine .

Dizin yapısını oluşturmak için bu tür bir algoritma kullanırdım:

  1. İlk önce, en az 12 basamaklı dizginiz olana kadar dizilişin başında sıfırlarla girin. Dosyanızın adı bu. Bir sonek eklemek isteyebilirsiniz:
    • 12345 -> 000000012345.jpg
  2. Daha sonra dizeyi, her bloğun bir dizin seviyesini gösterdiği 2 veya 3 karakter bloklarına bölün. Sabit sayıda dizin seviyesine sahip olun (örneğin 3):
    • 000000012345 -> 000/000/012
  3. Dosyayı oluşturulan dizinin altına kaydedin:
    • Böylece dizisi kimliğine sahip dosyasının tam yol ve dosya dosya adı 123olduğunu 000/000/012/00000000012345.jpg
    • Sıra kimliğine sahip dosya 12345678901234için yol123/456/789/12345678901234.jpg

Dizin yapıları ve dosya depolama hakkında dikkat edilmesi gereken bazı şeyler:

  • Yukarıdaki algoritma, her yaprak dizininin en fazla 1000 dosyaya sahip olduğu bir sistem sunar (eğer toplamda en az 1 000 000 000 000 dosya varsa)
  • Bir dizinin kaç dosya ve alt dizin içerebileceği konusunda sınırlamalar olabilir, örneğin Linux'taki ext3 dosya sisteminin bir dizin başına 31998 alt dizin sınırı vardır.
  • Normal araçlar (WinZip, Windows Gezgini, komut satırı, bash kabuğu vb.), Her bir dizinde çok sayıda dosya varsa, çok iyi çalışmayabilir (> 1000)
  • Dizin yapısının kendisi biraz disk alanı kaplar, bu nedenle çok fazla dizin istemeyeceksiniz.
  • Yukarıdaki yapıyla, dizin yapılarınızı karıştırırsanız, sadece dosya adına bakarak resim dosyasının doğru yolunu her zaman bulabilirsiniz.
  • Birkaç makineden dosyalara erişmeniz gerekiyorsa, dosyaları bir ağ dosya sistemi üzerinden paylaşmayı düşünün.
  • Çok sayıda dosyayı silerseniz, yukarıdaki dizin yapısı çalışmaz. Dizin yapısında "delik" bırakır. Ancak herhangi bir dosyayı silmediğiniz için sorun yok.

1
çok ilginç! Dosyayı bölmek ... Bunu düşünmedim. Bunun yapmanın zarif yolu olduğunu varsayıyorum: -?
s.mihai

37
Dizin dağıtımının yanı sıra, dosyanın adı olarak bir karma (MD5 gibi) kullanmak işe yarar. Dosyaların bütünlüğü sadece isimlendirme şemasına bir yan fayda sağlamakla kalmaz (kolayca kontrol edilir), aynı zamanda dizin hiyerarşisi boyunca makul bir dağılım bile elde edersiniz. Öyleyse "f6a5b1236dbba1647257cc4646308326.jpg" adlı bir dosyanız varsa, "/ f / 6" (ya da istediğiniz kadar derin) saklarsınız. 2 seviye derinliğinde, ilk 1m dosyalar için 256 dizin veya dizin başına 4000 dosyadan az verir. Yeniden dağıtımın daha derin bir plana göre otomatikleştirilmesi de çok kolay olacaktır.

+1 Bu cevabın henüz yayınladığım cevaba benzer olduğunu farkettim.
3dinfluence

1
Dosya sistemini kullanmaya ve klasör adlarına "dilimlemek" için yapay bir tanımlayıcı yaratmaya kesinlikle katılıyorum. Ancak aynı zamanda tanımlayıcıların rastgele bir dağılımını elde etmeye çalışmalısınız, yani bir sıra numarası kullanmayın. Bu, daha dengeli bir klasör ağacına sahip olmanızı sağlar. Ek olarak, rastgele dağıtımla ağacı daha kolay bir şekilde birden fazla dosya sistemine bölebilirsiniz. Ayrıca, dedup açık olan ve her dosya sistemi için az miktarda bir ZFS tabanlı SAN kullanırdım. SAN'a erişmek için iSCSI kullanarak NTFS'yi kullanabilirsiniz.
Michael Dillon

2. adımda sağdan sola giderseniz dosyalar eşit olarak dağıtılır. Ayrıca sınırsız sayıda dosyada olabileceğiniz için yeterince sıfır doldurmadığınız konusunda endişelenmenize gerek yok
ropo

31

2 kuruşa değecek bir olumsuz tavsiyeye değeceğim: Veritabanına gitme.

Yıllardır görüntü saklama veritabanları ile çalışıyorum: Sık sık değiştirilmiş, büyük (1 meg-> 1 gig) dosyalar, sıklıkla değişti, dosyanın çok sayıda sürümüne makul bir şekilde erişildi. Büyük dosyaların depolanmasıyla karşılaştığınız veritabanı sorunları ile uğraşmak son derece zahmetlidir, yazma ve işlem sorunları düğümlüdür ve büyük tren enkazlarına neden olabilecek kilitleme sorunlarıyla karşılaşırsınız. Ben DBCC komut dosyalarını yazma ve normal olan her insan gerekenden daha yedeklerden tabloları kavuşmasını daha pratik olması hiç yok.

Çalıştığım yeni sistemlerin çoğu, dosya deposunu dosya sistemine itti ve dizin oluşturmanın dışında hiçbir şey için veritabanlarına güveniyor. Dosya sistemleri bu tür bir kötüye kullanım için tasarlanmıştır, genişletilmesi çok daha kolaydır ve bir girdi bozulursa nadiren tüm dosya sistemini kaybedersiniz.


Evet. not alındı!
s.mihai

5
SQL 2008'in FILESTREAM veri türüne baktınız mı? Veri tabanı ve dosya sistemi depolaması arasında bir geçiş.
NotMe

Hızlı ve nadir G / Ç işlemleri yaparken bir veritabanı yerine dosya sunucusuna yapışmayı + 1'leyin.

Veri tabanı başına birkaç yüz dokümanı veya resmi saklıyorsanız - saklamak için veritabanı kullanmanın bir dezavantajı varsa?
Bip

1
+1 ... bir dosya sistemi zaten bir çeşit "veritabanı" dır (elbette ntfs), neden aşırı karmaşık hale getirdi ki?
akira

12

Ben bununla uğraşmak zorunda olan sitelerin çoğunun, dosyaların klasörlerde eşit bir şekilde dağıldığından emin olmak için bir tür karma kullandığını düşünüyorum.

Öyleyse, bunun gibi bir dosyaya sahip olduğunuzu söyleyin. 515d7eab9c29349e0cde90381ee8f810
Bunu aşağıdaki konumda saklayabilirsiniz ve her bir klasördeki dosya sayısını düşük tutmak için ne kadar derinlemesine ihtiyacınız olduğunu kullanabilirsiniz.
\51\5d\7e\ab\9c\29\349e0cde90381ee8f810.jpg

Bu yaklaşımı birçok kez aldım Bu dosya karışmalarını insan tarafından okunabilir bir adla ve başka hangi meta verilerini saklamak için ihtiyacınız olduğunu belirlemek için yine de bir veritabanına ihtiyacınız var. Fakat bu yaklaşım oldukça iyi ölçeklenir, karma adres alanını birden fazla bilgisayar ve / veya depolama havuzu vb. Arasında dağıtmaya başlayabilirsiniz.


2
Git benzer bir yaklaşım kullanıyor: git-scm.com/book/tr/v2/Git-Internals-Git-Objects (bu cevabı geri almak için)
aexl

11

İdeal olarak, özel sabit sürücü kurulumunuz, önbelleğe alma, kullanılabilir bellek vb. Bu sonuçları değiştirebileceğinden, çeşitli yapılar için rasgele erişim süreleri üzerinde bazı testler yapmalısınız.

Dosya adları üzerinde kontrol sahibi olduğunuzu varsayarsak, onları dizin başına 1000s düzeyinde bölümleyeceğim. Ne kadar fazla dizin eklerseniz, o kadar fazla inode yakarsınız, bu yüzden burada bir zorlama var.

Örneğin,

/ [0-99] / [0-99] / dosya / kök

Not: http://technet.microsoft.com/en-us/library/cc781134(WS.10).aspx , NTFS kurulumunda daha fazla ayrıntıya sahiptir. Özellikle, "Bir NTFS klasöründe çok sayıda dosya kullanıyorsanız (300.000 veya daha fazla), daha iyi performans için kısa dosya adı oluşturmayı devre dışı bırakın ve özellikle de uzun dosya adlarının ilk altı karakteri benzerse".

Ayrıca ihtiyacınız olmayan dosya sistemi özelliklerini devre dışı bırakmaya da bakmalısınız (örneğin, son erişim zamanı). http://www.pctools.com/guides/registry/detail/50/


3
8.3 dosya adı oluşturma ve son erişim zamanını devre dışı bırakmak için +1; "çok sayıda [dosya]" ve "NTFS" (Windows) okuduğumda aklıma ilk gelenler bunlardı.
rob

aşağı bağlantı ........................
Pacerier

7

Ne yaparsanız yapın, hepsini bir dizinde saklamayın.

Bu görüntülerin adlarının dağılımına bağlı olarak, görüntülerin 2. harfi için başka bir alt klasör kümesinin bulunduğu tek harfli üst düzey klasörlerin bulunduğu bir dizin yapısı oluşturabilirsiniz.

Yani:

Klasör img\a\b\c\d\e\f\g\'abcdefg' ile başlayan görüntüleri vb. İçerir.

Gereken kendi derinliğini kendin getirebilirsin.

Bu çözümle ilgili en güzel şey, dizin yapısının etkin bir sözlüğe / sözlük gibi davranmasıdır. Bir görüntü dosyası adı verildiğinde, dizini ve bir dizini verildiğinde, oraya giden bir görüntü alt kümesini bileceksiniz.


\ a \ b \ c \ d \ e \ f \ şuan yapıyorum, bunu yapmanın akıllıca bir yolu olduğunu düşünüyordum.
s.mihai

1
Bu, fiziksel olarak nasıl depolanacağına dair genel kabul görmüş bir çözümdür. Açık bir şekilde resim URL’lerini oluşturmak, resim dosyası adına göre dinamik olarak kolayca yapılabilecek bir şeydir. Ayrıca, onlara hizmet vermek için, yükleme sürelerini hızlandırmak için img-a, img-b alt etki alanlarını görüntü sunucusunda tanıtabilirsiniz.

2
Ve "1 hepsini bir dizinde saklamayın" için +1. Bir sunucuya 47000'den fazla dosyayı tek bir klasörde yerleştiren eski bir sistemi destekliyorum ve Explorer'ın sadece klasörü açması bir dakika sürüyor.
Mark Ransom

5
Bir \ b \ c \ d \ e \ f \ g yapmak, dizin yapısını çok derin yapar ve her dizin sadece birkaç dosya içerir. Dizin seviyesi başına birden fazla harf kullanmak daha iyidir, örneğin, ab \ cd \ ef \ veya abc \ def \. Dizinler ayrıca diskten yer kaplar, bu nedenle çok fazla istemezsiniz.
Juha Syrjälä

2
Tek bir dizinde 4 + milyon dosya bulunan bir uygulamayı desteklemek zorunda kaldım; şaşırtıcı derecede iyi çalıştı, ancak klasörü açmak için ASLA kaşif alamazsınız, sürekli olarak yeni ilaveleri sıralardı. NTFS için +1, ölmeden başa çıkabilmek.
SqlACID

5

Bunları dosya sisteminde saklardım ancak bu, dosya sayısının ne kadar hızlı büyüyeceğine bağlıdır. Bu dosyalar web'de barındırılıyor mu? Bu dosyaya kaç kullanıcı erişebilir? Size daha iyi bir tavsiyede bulunmadan önce cevaplanması gereken sorular bunlar. Ayrıca Facebook'tan Haystack'a bakardım, görüntüleri depolamak ve sunmak için çok iyi bir çözüm sunarlar.

Ayrıca, dosya sistemini seçerseniz, bu dosyaları dizinlerle bölümlemeniz gerekecektir. Bu konuya baktım ve bir çözüm önerdim ama bu hiçbir şekilde mükemmel değil. Blogumda daha fazla okuyabileceğiniz karma tablosu ve kullanıcılar tarafından bölümlere ayrılıyorum .


Görüntüler sık ​​erişim için uygun değildir. bu yüzden bu konuda hiçbir sorun yok. sayıları oldukça hızlı artacak. 1 milyon olacağını tahmin ediyorum. 1 ay içinde işaretleyin.
s.mihai

programcı görüşüne ilgi duyuyorum, böylece fazla
düşünmüyorum

Hızlı erişime ihtiyacınız yoksa Haystack muhtemelen sizin için değildir. Bölümler için Dizinler kullanmak benim görüşüme göre en basit çözümdür.
Lukasz

5

4 milyon resimli bir fotoğraf mağaza sistemimiz var. Veritabanını sadece meta veriler için kullanıyoruz ve tüm görüntüler dosya sisteminde, ters adlandırma sistemi kullanılarak depolanıyor, burada klasör adları dosyanın son basamağından, son 1, vb. örneğin: 000001234.jpg, 4 \ 3 \ 2 \ 1 \ 000001234.jpg gibi dizin yapısında saklanır.

Bu program veritabanındaki kimlik indeksi ile çok iyi çalışır, çünkü tüm dizin yapısını eşit şekilde doldurur.


4

Hızlı nokta, DB bir dosya yolu saklamak gerekmez. Dosyalarınızı tanımladığınız şekilde adlandırılmışsa, yalnızca bir sayısal değer depolayabilirsiniz. Ardından, daha önce tartışılan iyi tanımlanmış depolama planlarından birini kullanarak, dizini bir sayı olarak alabilir ve dizin yapısını geçerek dosyayı çok hızlı bir şekilde bulabilirsiniz.


: -? iyi hızlı nokta. Sadece şimdi yolu oluşturmak için bir algoritmaya sahip değilim.
s.mihai


4

Resimlerinizin benzersiz bir şekilde adlandırılması gerekecek mi? Bu görüntüleri üreten süreç aynı dosya adını bir kereden fazla üretebilir mi? Hangi cihazın dosya adını oluşturduğunu bilmeden söylemek zor ancak cihazın 'sıfırlandığını' söyleyin ve yeniden başlattıktan sonra görüntüleri en son 'sıfırlandığında olduğu gibi adlandırmaya başlar - böyle bir endişe ise ..

Ayrıca, bir ay içinde 1 milyon resme ulaşacağınızı söylüyorsunuz. Peki ya bundan sonra? Bu görüntüler dosya sistemini ne kadar hızlı doldurmaya devam edecek? Bir noktada zirveye mi çıkacaklar ve yaklaşık 1 milyon TOTAL imgesiyle seviye atlayacaklar mı yoksa her ay büyümeye ve büyümeye devam edecek mi?

Sizden soruyorum çünkü dosya sisteminizi ay önce, sonra görüntü ile tasarlamaya başlayabilirsiniz. Görüntüleri böyle bir dizin yapısında saklamanızı önerebilirim:

imgs\yyyy\mm\filename.ext

where: yyyy = 4 digit year
         mm = 2 digit month

example:  D:\imgs\2009\12\aaa0001.jpg
          D:\imgs\2009\12\aaa0002.jpg
          D:\imgs\2009\12\aaa0003.jpg
          D:\imgs\2009\12\aaa0004.jpg
                   |
          D:\imgs\2009\12\zzz9982.jpg
          D:\imgs\2010\01\aaa0001.jpg (this is why I ask about uniqueness)
          D:\imgs\2010\01\aab0001.jpg

Ay, yıl, hatta gün bile güvenlik tipi görüntüler için iyidir. Yaptığınız şeyin bu olup olmadığından emin değilim ama bunu her 10 saniyede bir fotoğraf çeken bir ev güvenlik kamerasıyla yaptım ... Bu sayede uygulamanız belirli bir zamana, hatta görüntünün oluşturulduğunu düşündüğünüz bir aralığa inebilir . Veya, yıl yerine, ay - görüntü dosyasının kendisinden elde edilebilecek başka bir "anlam" var mı? Verdiğim tarih örneği dışındaki diğer tanımlayıcılar?

İkili verileri DB'de depolamaz. Bu tür şeylerle asla iyi performans / şans bulamadım. 1 milyon görüntü ile iyi çalıştığını hayal bile edemiyorum. Dosya adını saklardım, hepsi bu. Hepsi JPG olacaksa, uzantıyı bile saklamayın. Bir işaretçiyi dosyanın sunucusuna, sürücüsüne, yoluna vb. Depolayan bir kontrol tablosu oluşturabilirim. Bu şekilde bu görüntüleri başka bir kutuya taşıyabilir ve yine de onları bulabilirsiniz. Anahtar kelimelerinizi etiketlemek için ihtiyacınız var mı? Öyleyse, bu tür bir etiketlemeye izin veren uygun tablolar oluşturmak istersiniz.

Siz / diğerleri ben cevaplarken bu fikirleri ele almış olabilirsiniz .. Umarım bu yardımcı olur ..


1.tüm dosyalar benzersiz bir şekilde adlandırılacaktır. 3. Gelecekte bir noktada dosyaların bir çeşit etiketlenmesi olacak, bu yüzden bir çeşit kimlik verisini db'de saklamak istiyorum.
s.mihai

3

Çeşitli cihazların durumunu belgelemek için bir yılda 8,4 milyon görüntü saklayan bir projede yer alıyorum. Daha yeni görüntülere daha sık erişilir ve bir başkasının arşivlere girmesine neden olan bir durum bulunmazsa, eski görüntülere nadiren ihtiyaç duyulur.

Bu kullanıma dayanarak benim çözümüm, görüntüleri artımlı olarak sıkıştırılmış dosyalara sıkıştırmaktı. Görüntüler JPG'dir, her biri yaklaşık 20kB'dir ve fazla sıkıştırmazlar, bu nedenle ZIP sıkıştırma şeması yoktur. Bu yalnızca onları sürücüden sürücüye taşımak veya dosya listesine bakmak konusunda NTFS'nin hız konusunda büyük ölçüde yardımcı olan tek bir dosya sistemi girdisinde birleştirmek için yapılır.

Bir günden daha eski görüntüler "günlük" bir zip halinde birleştirilir; bir aydan daha eski fermuarlar kendi "aylık" zip'lerinde birleştirilir; ve nihayet bir yıl içinde bir şeye artık ihtiyaç duyulmaz ve sonuçta silinir.

Bu sistem iyi çalışır, çünkü kullanıcılar dosyalara göz atabilir (işletim sistemi veya birkaç istemci uygulaması üzerinden) ve her şey aygıt adlarına ve zaman damgalarına göre adlandırılır. Genel olarak bir kullanıcı bu iki bilgiyi bilir ve milyonlarca görüntüden birini hızlı bir şekilde bulabilir.

Bunun muhtemelen sizin özel detaylarınızla ilgili olmadığını biliyorum ama paylaşacağımı düşündüm.


2

Belki de dosya adındaki tüm bilgileri içeren veya (daha sonra göz atmak için daha iyi) dizinlere bölerek oluşturulmuş bir tarihe dayalı adlandırma programı. Ne sıklıkta görüntü oluşturduğunuza bağlı olarak aşağıdakileri düşünebilirim:

  • Her gün birkaç görüntü oluşturulur: Year/Month/Day/Hour_Minute_Second.png
  • Ayda bir çift: Year/Month/Day_Hour_Minute_Second.png

vb. Anladın mı?


zaman içinde sürekli olarak oluşturulmazlar, bu yüzden bazı klasörler şişman olur ve diğerleri kalır ... ince :))
s.mihai

Belli ki her bir klasörü oluşturmak zorunda değilsiniz , çünkü bu şemaya uyduğunuzdan. Hatta Year/Month/Day/Hour/Minute- oranlar en yüksek olduğu zaman görüntülerin ne sıklıkta üretildiğine bağlı olarak kaç tane klasör seviyesine ihtiyacınız olduğuna karar verebilirsiniz - ve sonra boş bırakılacak klasörler oluşturmayın.
Tomas Aschan

2

Tarih tabanlı bir klasör yapısı oluşturmaya meyilliyim, örneğin \ year \ month \ day ve dosya adları için zaman damgaları kullandım. Gerekirse, görüntüler o kadar hızlı oluşturulacaksa zaman damgası ek bir sayaç bileşenine sahip olabilir, bir milisaniyede birden fazla olabilir. Adlandırma sıralaması için en önemli ila en az önemli bir sırayı kullanarak, bulma ve bakım çok kolaydır. örneğin, hhmmssmm [seq] .jpg


2

Olağanüstü durum kurtarmayı düşünüyor musunuz?

Burada önerilen çözümlerden bazıları, dosya adının yönetilmesiyle sonuçlanır (fiziksel dosya taşınmışsa gerçekte hangi dosyanın olduğunu izleyeceksiniz). Ana dosya konumları listeniz bozulursa, küçük bir kabuk, er, powershell, script;) ile yeniden oluşturabilmeniz için benzersiz bir fiziksel dosya adı tutmanızı öneririm.

Burada okuduklarımdan itibaren, tüm bu dosyalar tek bir dosya sisteminde depolanmış gibi geliyor. Bunları birden fazla makinede birden fazla dosya sistemine kaydetmeyi düşünün. Kaynaklarınız varsa, güç kaynağını kaybetmeniz ve değiştirmenin 2 gün sürmesi durumunda her bir dosyayı iki farklı makineye depolama sistemi belirleyin.

Dosyaları makineler veya dosya sistemleri arasında taşımak için ne tür prosedürler oluşturmanız gerektiğini düşünün. Bunu sisteminizle yapabilme yeteneği canlı ve çevrimiçidir, yolda ciddi baş ağrısından kurtulabilirsiniz.

Artımlı sayı sayacınızın (veritabanı kimliği sütunu?) Karışması durumunda, bir GUID'i artan bir sayı yerine fiziksel bir dosya adı olarak kullanmayı düşünebilirsiniz.

Uygunsa, Amazon S3 gibi bir CDN kullanmayı düşünün.


2

Bu ölçekte resimler sunmadığım halde, daha önce 400MHz'lik bir makinede ~ 25k resimler sunmak için küçük bir galeri uygulaması yazdım. 512 MB RAM ya da öylesine. Bazı deneyimler;

  • Her ne pahasına olursa olsun ilişkisel veritabanlarından kaçının; Veritabanları, şüphesiz, veri işleme konusunda akıllı olsalar da, bu tür kullanımlar için tasarlanmamışlardır ( dosya sistemleri adı verilen için uzmanlaşmış, hiyerarşik anahtar-değer veritabanları ). Bir önseziden başka bir şeyim olmasa da, eğer gerçekten çok büyük damlalar atarsanız, DB önbelleğinin pencereden dışarı çıkacağına bahse girerim. Kullanılabilir donanımım küçükken, görüntü aramada DB'ye hiç dokunmama büyüklük emri verdi.

  • Dosya sisteminin nasıl davrandığını araştırın; ext3'te (ya da ext2 idi - hatırlayamıyorum), alt dizinlere ve dosyalara etkili bir şekilde bakabilmenin sınırı 256 işaretindeydi; herhangi bir klasörde sadece bu kadar çok dosya ve klasöre sahip olmak. Yine, gözle görülür hızlanma. NTFS hakkında bir şey bilmeme rağmen, XFS gibi şeyler (hatırladığım kadarıyla B ağaçlarını kullanan) son derece hızlı, çünkü çok hızlı arama yapabiliyorlar.

  • Verileri eşit bir şekilde dağıtın; Yukarıdakileri denediğimde, verileri tüm dizinlere eşit bir şekilde dağıtmaya çalıştım (URL'nin bir MD5'ini yaptım ve bunu dizinler için kullandım; /1a/2b/1a2b...f.jpg). Bu şekilde performans sınırını ne olursa olsun vurmak daha uzun sürer (ve dosya sistemi önbelleği böyle büyük veri kümelerinde zaten geçersizdir). (aksine, sınırların daha erken nerede olduğunu görmek isteyebilirsiniz; daha sonra her şeyi ilk mevcut dizine atmak istersiniz.


2

Bu konuda oyuna geç kalabilirsin. Ancak, bir çözüm (kullanım durumunuza uygunsa) dosya adı karma olabilir. İyi dağıtılmış bir dizin yapısı oluştururken, dosyanın adını kullanarak kolayca çoğaltılabilir bir dosya yolu oluşturmanın bir yoludur. Örneğin, dosya adının karma kodunun baytlarını yol olarak kullanabilirsiniz:

String fileName = "cat.gif";
int hash = fileName.hashCode();
int mask = 255;
int firstDir = hash & mask;
int secondDir = (hash >> 8) & mask;

Bu yolun olmasına neden olur:

/172/029/cat.gif

Daha sonra cat.gifalgoritmayı yeniden oluşturarak dizin yapısını bulabilirsiniz .

HEX'i dizin adları olarak kullanmak, intdeğerleri dönüştürmek kadar kolay olacaktır :

String path = new StringBuilder(File.separator)
        .append(String.format("%02x", firstDir))
        .append(File.separator)
        .append(String.format("%02x", secondDir)
        .toString();

Sonuçlanan:

/AC/1D/cat.gif

Birkaç yıl önce bununla ilgili bir makale yazdım ve kısa süre önce Medium'a taşıdım. Birkaç detayı ve bazı örnek kodları var: Dosya Adı Hashing: Karma Dizin Yapısı Oluşturma . Bu yardımcı olur umarım!


Benzer bir şey kullanarak 1,8 milyar eşya saklıyoruz. İyi çalışıyor. Hızlı ve düşük çarpışma oranlarına sahip bir karma kullanın ve hazırsınız.
CVVS


1

Hepsi TÜM gerekmiyorsa ve bunları anında üretebiliyorsanız ve bunlar küçük görüntülerse, neden görüntü üreticinizin üzerinde LRU belleği veya disk önbelleği kullanmıyorsunuz?

Bu, sizi depolama alanından koruyabilir ve sıcak fotoğrafları mem'den saklayabilir mi?


1

Sadece zfs üzerinde bir test yaptım çünkü zfs'i seviyorum ve üzerinde sıkıştırma yaptığım 500 gig'lik bir bölümüm vardı. 50-100k dosyaları üreten ve 1/2/3/4/5/6/7/8 (5-8 seviye derinliğinde) iç içe dizinlere yerleştiren bir senaryo yazdım ve 1 hafta boyunca çalışmasına izin verdim. (Harika bir senaryo değildi.) Diski doldurdu ve yaklaşık 25 milyon dosya buldu. Bilinen bir yolu olan herhangi bir dosyaya erişim anında yapıldı. Bilinen bir yolu olan herhangi bir dizini listeleme anında yapıldı.

Ancak dosya listesinin bir sayısının alınması (bulma yoluyla) 68 saat sürdü.

Ayrıca bir dizine çok sayıda dosya koyarak bir test yaptım. Durmadan önce bir dizinde yaklaşık 3.7 milyon dosya buldum. Bir sayı almak için dizinin listelenmesi yaklaşık 5 dakika sürdü. Bu dizindeki tüm dosyaları silmek 20 saat sürdü. Ancak arama ve herhangi bir dosyaya erişim anında oldu.


1

Başka bir veritabanından bahsettiğimi görüyorum, ancak gönderinizden bundan bahsetmiyoruz. Her durumda, bu belirli noktadaki görüşüm şu: bir veritabanına bağlı kalmak veya dosya sistemine. İkisini karıştırmanız gerekiyorsa, buna dikkat edin. İşler daha da karmaşıklaşıyor. Ama yapmak zorunda kalabilirsiniz. Milyonlarca fotoğrafı bir veritabanında saklamak en iyi fikir gibi görünmüyor.

Aşağıdaki özelliklere ilginizi çekebilir, çoğu dijital fotoğraf makinesi dosya depolamasını yönetmek için takip eder: https://en.wikipedia.org/wiki/Camera_Image_File_Format

Temel olarak, gibi bir klasör oluşturulur 000OLYMPUSve fotoğraflar bu klasöre eklenir (örneğin DSC0000.RAW). Dosya adı sayacı DSC9999.RAWyeni bir klasöre ulaştığında ( 001OLYMPUS) oluşturulur ve görüntü tekrar eklenir, sayaç farklı bir önekle sıfırlanır (örneğin:) P_0000.RAW.

Alternatif olarak, dosya adının bölümlerini temel alan klasörler de oluşturabilirsiniz (zaten birkaç kez belirtilmiştir). Örneğin, fotoğrafınız adlandırılmışsa IMG_A83743.JPG, saklayın IMG_\A8\3\IMG_A83743.JPG. Uygulaması daha karmaşıktır ancak dosyalarınızı daha kolay bulmanızı sağlar.

Dosya sistemine bağlı olarak (bu biraz araştırma gerektirebilir), tüm görüntüleri tek bir klasöre atabilirsiniz, ancak deneyimlerime göre bu genellikle performans sorunlarına neden olabilir.


0

ZFS'ye bakmak isteyebilirsiniz (dosya sistemi, Sun'dan cilt yöneticisi) Saygılarımızla


0

Yolu çok büyük bir sayıdan oluşturmanın temiz bir yolu, onu kolayca hex'e dönüştürmek ve sonra bölmektir!

örneğin 1099496034834> 0xFFFF1212>FF/FF/12/12

public string GeneratePath(long val)
{  
    string hex = val.ToString("X");
    hex=hex.PadLeft(10, '0');
    string path="";
    for(int i=0; i<hex.Length; i+=2 )
    {
        path += hex.Substring(i,2);
        if(i+2<hex.Length)
            path+="/";
    }
    return path;
}

Depolayın ve yükleyin:

public long Store(Stream doc)
{
   var newId = getNewId();
   var fullpath = GeneratePath(newId)
   // store into fullpath 
   return newId;
}

public Stream Load(long id)
{
   var fullpath = GeneratePath(newId)
   var stream = ... 
   return stream;
}

Tam kaynak kodları: https://github.com/acrobit/AcroFS


-1

Ne yazık ki, çok sayıda küçük dosyayı yönetirken dosya sistemleri çok kötü (dizin veya derin dizin ağaçları başına birçok dosyada performans, yeniden başlatma zamanlarını kontrol etme, güvenilirlik), bu nedenle bir dosya sistemi kullanmak istiyorsanız, ZIP dosyalarını içeren yukarıdaki çözüm en iyisidir.

Bir veritabanı yöneticisi kullanmak şu ana kadar ki en iyi seçenek; örneğin BDB veya GDBM gibi basit bir tane; MySQL gibi bir göreli DBMS bile daha iyi olurdu. Yalnızca dosya sistemlerini ve veritabanlarını anlamayan tembel insanlar (örneğin işlemleri reddedenler gibi) dosya sistemlerini veri tabanı olarak kullanma eğilimindedir (ya da biraz daha nadir olarak, viceversa).


-2

Görüntüyü saklamak için ID ve BLOB içeren bir tablo içeren bir veritabanına ne dersiniz? Daha sonra, bir fotoğrafla daha fazla veri öğesini ilişkilendirmek istediğinizde yeni tablolar ekleyebilirsiniz.

Ölçeklemeyi bekliyorsanız, neden şimdi ölçeklenmiyorsunuz? Hem şimdi hem daha sonra IMO'dan zaman kazanacaksınız. Veri tabanı katmanını bir kez uygulayın, bu başlangıçtan oldukça kolaydır. Veya bir şeyler klasörlerle, dosya isimleriyle ve filan filanı ile uygulayın ve daha sonra MAX_PATH’ı patlatmaya başladığınızda başka bir şeye geçin.


5
Orada bulundum, yaptım, kanıtlayacak izleri var. Görüntüleri çok sayıda depolayan veritabanları, neredeyse inanılmayacak kadar huysuz ve fazla miktarda bakım gerektirmiyor. Yalnızca bir veritabanı tarafından yanıtlanabilecek belirli bir gereksiniminiz yoksa, dosya sisteminde saklamak çok daha iyidir (bizim sürüm
sürümümüzdü

1
Ve bir veritabanı içindeki dosyalarla uğraşmak için çok az sayıda dosya ve dosya sistemiyle uğraşmak için çok sayıda yardımcı program vardır.
Mark Ransom

2
Aman Tanrım. Lütfen büyük bir BLOB saklama alanı olarak veritabanı kullanmayın.
Neil N,

Eek. Veritabanlarının (hala?) BLOB'larla ilgili pek çok sorunu olduğunu bilmiyordum.

Bu kadar çok yorum yapan kötü bir çözümün hala + 1'i nasıl olabilir? OP'ye alınma (SO'dan geldiğini anlıyorum), ancak aşağı oy düğmesi bir sebeple burada!
Mark Henderson
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.