Büyük miktarda veri üzerinde çalışan algoritmaları sıralama


12

Büyük miktarda veri üzerinde çalışabilen, yani tüm veri seti aynı anda ana bellekte tutulamadığında bile çalışabilen sıralama algoritmaları arıyorum.

Şimdiye kadar bulduğum tek aday birleştirme sıralamasıdır: algoritmayı, tüm verileri bir kerede ana bellekte tutmadan her bir birleştirme sırasında veri kümenizi tarayacak şekilde uygulayabilirsiniz. Aklımda olan birleştirme sıralaması varyasyonu Bu makalede Teyp sürücüleri ile kullanma bölümünde açıklanmaktadır .

Bu iyi bir çözüm olduğunu düşünüyorum (karmaşıklık O (nx log (n)) ile ama ana belleğe sığmayan büyük veri kümeleri üzerinde çalışabilecek başka (muhtemelen daha hızlı) sıralama algoritmaları olup olmadığını bilmek merak ediyorum.

DÜZENLE

Yanıtların gerektirdiği gibi bazı ayrıntılar:

  • Verilerin periyodik olarak, örneğin ayda bir kez sıralanması gerekir. Birkaç kayıt eklemek ve veri kademeli olarak sıralanmış olması gerekmez.
  • Örnek metin dosyam yaklaşık 1 GB UTF-8 metnidir, ancak dosya 20 GB olsa bile sorunu genel olarak çözmek istedim.
  • Veritabanında değildir ve diğer kısıtlamalar nedeniyle olamaz.
  • Veriler başkaları tarafından bir metin dosyası olarak dökülür, bu metin dosyasını okumak için kendi kodum var.
  • Verilerin formatı bir metin dosyasıdır: yeni satır karakterleri kayıt ayraçlarıdır.

Aklıma gelen olası bir gelişme, dosyayı bellekte sıralanacak kadar küçük dosyalara bölmek ve son olarak yukarıda açıkladığım algoritmayı kullanarak tüm bu dosyaları birleştirmekti.


1
Ne tür veriler? Farklı veri setleri, amacınıza en uygun farklı algoritmalar anlamına gelebilir.
whatsisname

Bu bir metin dosyası ve satırları sıralamak zorundayım. Satırlar sabit uzunlukta değil ancak uzunluk çok fazla değişmiyor (kayıt başına yaklaşık 50 karakter).
Giorgio

3
Ortamınızı veya kısıtlamalarınızı bilmiyorum, ancak mümkün olduğunda sıralama için bir veritabanı kullanacağım. Bunun nedeni, neredeyse% 100 hataya dayanıklı olması ve kodumdan çok daha verimli olmasıdır.
NoChance

Linux / Java üzerinde çalışıyorum. Birleştirme sıralaması uyguladım ve oldukça sorunsuz çalışıyor gibi görünüyor. Birkaç milyon çizgiyi sıralamak oldukça zaman alıyor, ancak bunu arada bir yapmam gerekiyor.
Giorgio

@Giorgio, böyle bir algoritma uygulamanız iyidir. Üretim çalışmaları için hala bir veritabanı kullanmanızı öneririm. Sadece hız için değil, aynı zamanda güvenilirlik ve bakım kolaylığı için.
NoChance

Yanıtlar:


13

Sıralama ve arama ile ilgili kanonik referans Knuth, Vol. 3 . Oradan başlayın.

Kitap başlangıçta bilgisayarlar şimdi olduğundan çok daha küçük ve yavaş olduğunda geri yazılmıştır, bu da bellek dışı sıralama tekniklerini bugün algılandığından daha önemli hale getirmiştir.


2
Referans için teşekkürler: Knuth'un kitabında ilginç malzemeler bulacağımdan neredeyse eminim. Bellek yetersiz sıralama tekniklerinin bugün uygun olmadığından emin değilim. Belki ortak, günlük işler için değil, ancak çok büyük veri kümelerinin işlenmesi gereken birçok durum olduğunu hayal edebiliyorum.
Giorgio

Knuth'un algoritmaları her zaman yardımcı olur. Örneğin, bir yığın sıralama tamponu ile birleştirme sıralaması çok etkili ve uygulanması çok kolay olabilir.
Sulthan

4
Çok yararlı bir cevap değil çünkü atıfta bulunulan materyal ücretsiz değil. OP için bir cevap için googling'i öneririm. Bu tür bilgileri web'de kazarak bulabileceğiniz bir kitap almak için 50 $ dolar kabuk zorunda değilsiniz. Tabii ki, bunu muhtemelen ( ahem ) belirli sitelerden ücretsiz olarak indirebilirsiniz . Kabul edilen bir cevabı hak etmiyor.
Thomas Eding

1
@ThomasEding, "kitaplık" adı verilen ve "kitap" adı verilen eski bilgi depolama ve alma cihazlarının büyük miktarlarını içeren bu şeyler var. "Kütüphaneler", "kitapları" ÜCRETSİZ KREDİ için kullanılabilir hale getirir. Belirli bir "kütüphane" aradığınız özel "kitap" içermiyorsa, "kütüphane" nin "kitap" ı başka bir "kütüphane" den ödünç almalarına izin veren "kütüphaneler arası ödünç" adlı ÜCRETSİZ bir hizmet de sunarlar. size ödünç verin.
John R. Strohm

6

UNIX sortkomutundaki gibi harici R-Way birleştirme iyi bir alternatiftir. Formülasyonunuzdan, "birleştirme sıralaması" ile kastedilen algoritma olup olmadığından emin değilim ve bilmiyorsanız, bir göz atın.


Teşekkürler. Harici R-Way birleşmesi aklımdakilerden farklı görünüyor. İlginç okuma.
Giorgio

4

Daha fazla özellik olmadan "Merge Sort" muhtemelen alacağınız en iyi cevaptır, ancak gereksinimlerinize bağlı olarak daha akıllı bir şey uygulayabilirsiniz.

Örneğin, dosyanın bir bellek içi dizinini oluşturabilir, ardından tüm değerleri aynı anda kopyalayıp çeşitli anahtar değerlerin konumunu önbelleğe alabilir misiniz? 1/2 bir kerede belleğe sığar mı, yoksa 1/1000000 mü? Eğer ikinciyse, o zaman belleğe bir dizin sığdıramayabilirsiniz, ilki her iki yarıyı da daha verimli bir şekilde sıralayabilir ve ardından son bir adımda birleştirebilirsiniz.

Cehennem, belirtmediniz çünkü verilerinizin bir veritabanında olması mümkündür, eğer öyleyse sadece bir dizin tablosu oluşturabilir ve iyi çağırabilirsiniz (sanırım durum böyle değil, ama sadece durumunuz böyle karmaşık bir sorunu çözmek için kritik öneme sahiptir).

Sadece bir kez yapmak istiyorsanız ve çok hızlı bir kesmek istiyorsanız, unix çalıştırıyorsanız harici birleştirme sıralaması iyi bir başlangıç ​​gibi görünüyor (görünüşte yerleşik olduğu için)

Düzeni saklamanız gerekiyorsa ve her zaman tek bir kayıt ekliyorsanız, bir ekleme sıralaması gerekli olacaktır (Sıralanan verilere tek bir kayıt eklemek her zaman bir ekleme sıralamasıdır).

Verileri "Okuyan" kodu kontrol edebilir misiniz? Eğer öyleyse, birçok indeksleme biçimi (verileri diskte hareket ettirerek sıralamak yerine) A LOT'a yardımcı olacaktır (aslında mutlak bir gereklilik olacaktır).

Yani:

  • Yerinde mi yoksa birden çok dosyada mı?
  • Bir kerelik, periyodik veya her zaman sıralanmış olarak tutmak?
  • Bellekten ne kadar büyük (Veri kümesinin tamamından kaç bellek yükü geçecek)?
  • Veritabanında mı? Olabilir mi?
  • Verileri okuyan kodu kontrol ediyor musunuz, yoksa diğerleri doğrudan bir dosyayı boşaltıyor mu?
  • Dosya formatı? (Metin? Sabit kayıt?)
  • Sormadığım başka özel durumlar var mı?

Cevap için teşekkürler. "Yerinde veya birden fazla kayıtta" ile ne demek istiyorsun?
Giorgio

Üzgünüm, cevabımı kanıtlamamalıydı - Birden fazla dosya demek istedim. Yerinde hemen hemen sabit kayıt boyutları ve muhtemelen hangi noktada bir veritabanı isteyeceğiniz dizine ekleme anlamına gelir.
Bill K

Hayır, yerinde değil: kayıtlar sabit boyutta değil. Mevcut uygulamam için dört geçici dosya kullanıyorum.
Giorgio

Çıkışı kodla yorumlayabilir misiniz veya belirli bir formatta mı olması gerekir (düz metin dosyası?) Ne sıklıkta sıralanması gerekir - her şey eklendiğinde veya sadece ara sıra? Bir şey eklendiğinde sadece sonuna eklenir veya ekleyen kodu yazabilir misiniz?
Bill K

Her satır bir kayda ayrıştırılabilir (dosya bir CSV dosyasıdır) ancak alanların çoğu metindir. Arada bir sıralanması gerekir (örneğin her ay) ve mevcut uygulamamla sıralama yaklaşık 1 saat sürer. Bir satır eklemek için doğru yere satır ekleyen kodu yazabilirsiniz: şimdiye kadar sahip kod ile böyle bir araç yazmak için bana 20 dakika sürer.
Giorgio

3

Gerçekten ölçeklenebilir bir çözüm istiyorsanız, map-reduce ile standart sıralama uygulaması TeraSort'a göz atmalısınız; StackOverflow hakkında daha fazla bilgi .


1
+1: İlginç bağlantı. Birleştirme sıralaması, haritanın sıralama alt listelerine, azaltma ise birleştirmeye karşılık gelen bir harita / azaltma örneği değil mi?
Giorgio

Öyle görünebilir, ama bunu kendiniz yazmak yerine Hadoop'u sizin için yapabilirsiniz.
m3th0dman

1

Bir kova türüyle ilgileniyor olabilirsiniz . Ortalama vaka performansı doğrusal süredir.

= O (n + d) n: elemanların sayısı ve d = verileriniz hakkında bir sezginiz varsa, yani en büyük sayının uzunluğu. Eğer kaç 'basamak' uzunluğunu biliyorsanız en büyük rakamınızdır. 2 milyon 6 basamaklı numaranız varsa => 0 (n) böylece doğrusal.


0

(Veri sürekli varsa) dış birleştirme sıralaması algoritması kullanarak, ya da bir paket sıralama ile sıralama sayımı (veri kesikli ve eşit dağılmış ise) kovalar için sıralama bir uygulama olarak.

Muhtemelen en iyi yaklaşım, artış küçükse kendi dizin / eşleme dosyanızı oluşturmaktır.

  1. Bir şekilde "veritabanınızı" sipariş edin
  2. Her girişe bir tamsayı atayın (1, 2, 3, 4, ..., n) (daha iyi: bazı seyrek dizinler kullanın)
  3. Bir artış eklerken, sol sayının daha az veya eşit olduğu ve doğru sayının daha büyük veya eşit olduğu bir boşluk bulun (ikili aramanın değiştirilmiş bazı sürümlerinde zor olmamalıdır)
  4. Boşluklar yeterince büyük olsa da ekleyin, değilse: sadece yeniden dizin (bir daha asla sıralamayın) :-)

0

Sınırlı belleğe sahip tek bir makinede büyük veri sıralama ve arama görevini basitleştirmek için büyük kuyruk ve büyük dizi adı verilen bazı soyut yapılar inşa ettim. Temel olarak, kullanılan algoritma yukarıda bahsettiğiniz algoritmaya benzer - harici birleştirme sıralaması.

Tek bir makinede 9 saatte 128 GB veri (her öğe 100 bayt) sıralayabilir ve sonra sıralı verileri neredeyse hiç zaman harcamadan ikili olarak arayabilirim.

İşte benim açık kaynak büyük kuyruk ve büyük dizi yapıları kullanarak büyük veri arama hakkında bir yazı.

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.