Hızlı etiket arama için algoritma


16

Sorun şudur.

  • Her biri bir dizi T etiketine sahip olan bir dizi basit varlık E vardır. Her varlığın rastgele sayıda etiketi olabilir. Toplam varlık sayısı 100 milyona yaklaşıyor ve toplam etiket sayısı yaklaşık 5000.

Yani ilk veriler şöyle:

E1 - T1, T2, T3, ... Tn
E2 - T1, T5, T100, ... Tk
..
Ez - T10, T12, ... Tl

Bu ilk veriler oldukça nadiren güncellenir.

  • Her nasılsa benim app böyle etiketler üzerinde mantıklı bir ifade oluşturur:

    T1 ve T2 ve T3 | (T5 &! T6)

  • Ne gerek verilen ifade ile eşleşen bir dizi varlık hesaplamak için (not - varlıkları değil, sadece sayı). Bu kesinlikle doğru olmayabilir.

Şimdi sahip olduğum basit bir bellek içi tablo araması, bana tek bir iş parçacığında 5-10 saniye yürütme süresi veriyor.

Merak ediyorum, bu şeyleri halletmenin etkili bir yolu var mı? Hangi yaklaşımı önerirsiniz? Bunun için bazı ortak algoritmalar veya veri yapıları var mı?

Güncelleme

İstendiği gibi biraz açıklama.

  1. Tnesneler aslında nispeten kısa sabit dizelerdir. Ama aslında önemli değil - her zaman bazı kimlikler atayabilir ve tamsayılar üzerinde çalışabiliriz.
  2. Onları kesinlikle sıralayabiliriz.

1
olduğu T1için aynı nesne referans E1, E2vb?
Reactgular

etiketler nasıl karşılaştırılabilir? etiketler T2 < T3her zaman doğru olacak şekilde sıralanabilir mi?
Reactgular

Etiketler ikili midir? Yani T1ya verili ya trueda falseverili E, girdiye göre değişken değil mi? (ie Model = "V5") Veya T1değişken bir ifade Model = <input>?
Bobson

Yanıtlar:


4

kendi kendine birleştirmeler kullanarak başvuru varlık ve başvuru kategorisi EntityCategoryarasında bir bağlantı tablosu olan sql bunu yapardı :eidcid

    select count(ec1.eid)
    from EntityCategory ec1 
    left join EntityCategory ec2 on ec1.eid=ec2.eid 
    left join EntityCategory ec3 on ec1.eid=ec3.eid 
    ...
    where 
      ec1.cid={categoryId1} and 
      ec2.cid={categoryId2} and
      ec3.cid={categoryId3} ...

1
+1, bu klasik DB bölgesi. Diğer cevap, manuel olarak nasıl kodlanacağı konusunda makul fikirlere sahip olabilir, ancak bu son çare olmalıdır.
MSalters

Ayrıca bunu çözmek için teknik olarak sql seçerdim. Çoğu veritabanı bu algoritmalar için oldukça optimize edilmiştir :)
winkbrace

3

Bu cevabı yazdıktan sonra, muhtemelen soruyu “çok geniş” olarak işaretlemeliyim - çağlar boyunca çeşitli stratejiler hakkında konuşabiliriz, sonunda verilerinizle bir kıyaslama ölçütü yürütülecektir.

Her etiket etkili bir şekilde bir tamsayı ile temsil edilebilir. Her varlığın bir dizi etiketi vardır. Doğru set uygulamasını seçmek önemlidir - hem B-ağaçları hem de sıralı diziler mümkündür. Bu set ile sadece üyelik testleri yapacağız. Her iki yapı bunu O (log t) ( varlık başına t etiketi ile ) olarak yaptığından, daha yoğun gösterimleri nedeniyle dizileri tercih ederim.

Şimdi O (n · log t · p) işlemindeki tüm varlıklar arasında filtreleme yapabiliriz ; burada p , karar verme karar ağacındaki ortalama yol uzunluğudur. Bu karar ağacı, bir karara hızlı bir şekilde ulaşılabilmesi için sipariş edilebilir. İstatistiksel veriler olmadan, yalnızca ortak alt ifadeyi hesaba katmak mümkündür.

Varlıkların aranma sırası gerçekten önemli değildir. Diğer taraftan bu tür endeksleri de varlıklar ilgili sıralamak için avantajlı olabilir 0için idinlenme yapar iken, tüm belli etiketine sahip. Bu , bu belirli etiketi ararken n'yi azaltır (karar ağacında bu ilk test olmalıdır). Bu, birden fazla seviyeye genişletilebilir, ancak bu işleri karmaşıklaştırır ve O (2 k ) hafızayı k ile alırseviyeleri. Birden fazla seviye ile, en yüksek kazancı olan etiketlere ilk önce karar verilmelidir, burada kazanım, aranması gerekmeyen varlıkların sayısı, atılma olasılığının katıdır. Kazanç 50:50 şans için veya varlıkların% 50'sinde bu belirli etikete sahip olduğunda maksimum olur. Bu, erişim kalıpları bilinmese bile optimize etmenizi sağlar.

Ayrıca, kullanılan her etikete göre varlıkları dizine alan kümeler de oluşturabilirsiniz; bunlardan biri için tüm varlıkları içeren bir küme, diğeri T1için T2. Belirgin bir (boşluk ve zaman) optimizasyonu, bir küme tüm öğelerin yarısından fazlasını içerdiğinde durmak ve bu etikete sahip olmayan öğeleri kaydetmek - bu şekilde, tüm etiketler için endeks oluşturmak ½ · n · talandan ( Toplamda t etiketi). Tamamlayıcı setlerin kaydedilmesinin diğer optimizasyonları zorlaştırabileceğini unutmayın. Yine, diziler için diziler (sıralama) yapardım.

Varlıklarınızı bir tamsayı aralığında da temsil ediyorsanız, dizin kümeleri için kullanılan alanı yalnızca sürekli bir aralığın başlangıç ​​ve bitiş üyesini kaydederek sıkıştırabilirsiniz. Uygulama açısından bu, bir girdinin aralığa bağlı mı yoksa normal girdi mi olduğunu belirtmek için büyük bir bitle yapılabilir.

Şimdi dizin kümelerimiz varsa (ve böylece etiketlerdeki istatistikler), tahminlerimizi optimize ederek, ilk önce olası olmayan özelliklerin test edilmesini optimize edebiliriz (başarısızlık stratejisi). Bu T1, yaygın ve T2nadir ise, yüklemin T1 & T2tüm T2dizin kümesi girişleri üzerinden yinelenerek ve her bir öğenin test edilerek değerlendirilmesi gerektiği anlamına gelir T1.

Dizin kümelerini uygulamak için sıralanmış diziler kullanırsak, birleştirme işlemleri olarak birçok değerlendirme adımı uygulanabilir. ve listelerini T1 & T2aldığımız , daha büyük girdilerin büyüklüğünde bir hedef dizi tahsis ettiğimiz T1ve T2her iki giriş de boş olana kadar aşağıdaki algoritmayı gerçekleştirdiğimiz anlamına gelir : If T1[0] < T2[0], T1++(başını atın). Eğer T1[0] > T2[0]öyleyse T2++. Her iki başına eşit ise, o zaman, hedef diziye üzerinden bu kopya sayısı ve her üç işaretçiler (artırmak T1, T2hedef). Yüklem ise T1 | T2, hiçbir öğe atılmaz, ancak daha küçük olan kopyalanır. Formun Bir dayanak T1 & ¬T2, aynı zamanda, bir birleştirme stratejisi kullanılarak uygulanabilir, ancak ¬T1veya T1 | ¬T2olamaz.

Yüklem karar ağacı sipariş edilirken bu göz önünde bulundurulmalıdır: Tamamlayıcılar ya bir RHS üzerinde &ya da son olarak nihai sayım belirlenirken ve gerçek öğelere bakılmak zorunda kalmadan yapılmalıdır.

Dizin kümeleri kullanılmadan, her iş parçacığı varlıkların bir parçası boyunca filtreleyebilir ve yüklemle eşleşen öğe sayısını döndürerek toplanabilir. Dizin kümelerini kullanırken, her iş parçacığına karar ağacında bir düğüm atanır. Sıralı setlere karşılık gelen iki giriş akışı alır ve birleştirilmiş bir akış döndürür. Karar ağacındaki her düğümün, bu alt ifadeyi yerine getiren tüm varlıkları temsil eden karşılık gelen bir kümeye sahip olduğuna ve kümelerin sıralaması nedeniyle, kümeyi birleştirmek için tüm kümeyi bir kerede bilmek gerekmediğine dikkat edin. .

Dizinlenmiş kümeleri birleştirmek veya bir varlık listesi aracılığıyla filtreleme gibi farklı stratejiler belirli bir dereceye kadar birleştirilebilir. Filtreleme çok öngörülebilir bir performansa sahiptir. Dizin kümelerinin kullanımının arama alanını önemli ölçüde azaltması için bir sorgu çok spesifikse, birleştirme işlemleri daha iyi olabilir. Birçok büyük giriş kümesinin birleştirilmesinin, kaba kuvvet aramasından çok daha kötü performansla sonuçlanabileceğini unutmamak önemlidir. Çok optimize edilmiş bir algoritma girdi boyutu, sorgu yapısı ve istatistiksel göstergelere göre uygun bir strateji seçecektir.

Bir yana, kısmi sonuçların önbelleğe alınması, inital çalışmayı hızlandırmasalar bile gelecekte benzer sorguların çalıştırılması bekleniyorsa faydalı olabilir.

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.