NoSQL'de kayıt ilişkilerini nasıl takip ediyorsunuz?


118

NoSQL KVP veya Belge veritabanlarındaki yabancı anahtarların ve dizinlerin eşdeğerini bulmaya çalışıyorum. Özet tablolar olmadığından (iki nesne arasındaki ilişkiyi işaretleyen anahtarlar eklemek için), verileri normal web sayfaları için yararlı olacak şekilde nasıl geri getirebileceğiniz konusunda gerçekten şaşkınım.

Diyelim ki bir kullanıcım var ve bu kullanıcı sitenin her yerine birçok yorum bırakıyor. Bu kullanıcıların yorumlarını takip etmenin tek yolu,

  1. Bunları kullanıcı nesnesine yerleştirin (bu oldukça işe yaramaz görünüyor)
  2. user_id:commentsGerektiği gibi alabilmem için her yorumun anahtarının bir listesini [comment: 34, comment: 197, vb.] İçeren bir değer oluşturun ve koruyun .

Ancak, ikinci örnek alarak yakında sen o yapımında 30 milyon kimlikleri içerebilir "active_comments" adlı bir anahtar gibi başka şeyler takip etmek için kullandığınızda bir tuğla duvar vuracak bir ton mal sadece bazı son bilmek her sayfayı sorgulamak için aktif yorumlar. Ayrıca , birçok sayfa aynı anda onu güncellemeye çalışabileceğinden, yarış koşullarına çok açık olacaktır .

Bir NoSQL veritabanında aşağıdaki gibi ilişkileri nasıl izleyebilirim?

  • Bir kullanıcının tüm yorumları
  • Tüm aktif yorumlar
  • [Anahtar kelime] ile etiketlenen tüm gönderiler
  • Bir kulüpteki tüm öğrenciler veya bir öğrencinin bulunduğu tüm kulüpler

Yoksa bunu yanlış mı düşünüyorum?


NoSQL veritabanlarında bunu yapmanın tek bir yolu yoktur, bu soru daha çok C programlarındaki ilişkileri nasıl izleyeceğimi sormakla ilgili.
stonemetal

3
Vay canına, o halde RDBMS'nin yerini alan NoSQL hakkındaki aldatmacanın imkansız olduğunu tahmin ediyorum.
Xeoncross

11
Evet, NoSQL kesinlikle abartılıyor. Yeni teknolojilerin doğru koşullarda yararlı olmadığını söylemiyorum, ancak RDBMS'nin yerini alacaklarını düşünmek saçma. Bkz. En.wikipedia.org/wiki/Hype_cycle
Bill Karwin

1
Sadece bir 'kullanıcılar' koleksiyonunuz ve bir yorum koleksiyonunuz olmaz mıydı? Ve sonra, her yorum, değeri bir kullanıcı kimliğine referans olan bir 'yazar' özelliği olarak mı?
CodeFinity

Yanıtlar:


187

"NoSQL yolu" ile çoktan çoğa ilişkilendirmelerin nasıl saklanacağına dair tüm yanıtlar aynı şeye indirgenir: verileri yedekli depolama.

NoSQL'de, veritabanınızı veri varlıkları arasındaki ilişkilere göre tasarlamazsınız. Veritabanınızı, ona karşı çalıştıracağınız sorgulara göre tasarlarsınız. İlişkisel bir veritabanını normal dışı hale getirmek için kullanacağınız ölçütlerin aynısını kullanın: eğer verilerin tutarlılığa sahip olması daha önemliyse (normalleştirilmiş tablo yerine virgülle ayrılmış bir listedeki değerleri düşünün), o zaman bu şekilde yapın.

Ancak bu, kaçınılmaz olarak bir tür sorgu için (örneğin, belirli bir makale için herhangi bir kullanıcı tarafından yapılan yorumlar), diğer türdeki sorguların (belirli bir kullanıcının herhangi bir makalesine ilişkin yorumlar) pahasına optimize eder. Uygulamanızın her iki tür sorgunun da eşit şekilde optimize edilmesi gerekiyorsa, normal olmayan duruma getirmemelisiniz. Ve benzer şekilde, verileri ilişkisel bir şekilde kullanmanız gerekiyorsa bir NoSQL çözümü kullanmamalısınız.

Normalden arındırma ve fazlalıkla ilgili, fazlalık veri kümelerinin birbiriyle senkronize olmaması riski vardır. Buna anormallik denir . Normalleştirilmiş bir ilişkisel veritabanı kullandığınızda, RDBMS anormallikleri önleyebilir. Normal olmayan bir veritabanında veya NoSQL'de, anormallikleri önlemek için uygulama kodunu yazmak sizin sorumluluğunuzdadır.

Bir NoSQL veritabanının sizin için anormallikleri önlemenin zor işlerini yapmasının harika olacağını düşünebilirsiniz. Bunu yapabilecek bir paradigma var - ilişkisel paradigma.


20
"Verileri ilişkisel bir şekilde kullanmanız gerekiyorsa, bir NoSQL çözümü kullanmamalısınız" - Öyleyse, NoSQL çalıştıran diğerleri bundan nasıl kurtulabilir? Uygulamanızı ilk tasarlarken verileri sorgulayacağınız tüm yolları nasıl bilebilirsiniz? Fox örneği, son yorumları, kullanıcıya göre yorumları, etikete göre yorumları, spam olarak işaretlenen yorumları, aktif yorumları, en yüksek puan alan yorumları, vb.
İsteyebilirim

14
Kesinlikle - NoSQL savunucularının iddia etmek istediği gibi "sadece çalışır" diye bir şey yoktur. Ya ilişkisel veri modellemeniz için önceden bir dizi analiz yaparsınız ya da en öncelikli sorgularınız için önceden bir dizi analiz yaparsınız ya da tasarımınızın hangi kısımlarını keşfederken proje boyunca bir dizi maliyetli yeniden düzenleme yaparsınız. önceden yeterince analiz almamış.
Bill

1
Verileri yedekli olarak depolarsak, bazı şeyleri nasıl güncellemeliyiz? Örneğin adını değiştirdi ve bazı yorumlar yazdı. Adı kullanıcı koleksiyonunda zaten değiştirildi, ancak yorum koleksiyonunda fazladan saklanan tüm isimler nasıl değiştirilir?
Mohammad Kermani

3
@ M98, Ah, bu stratejideki zayıflığı buldunuz. Güncellemeniz gereken tüm yerleri bilmeniz ve herhangi birini güncellediğinizde hepsini güncellemek için uygulamanıza kod yazmanız gerekir. İyi şanslar!
Bill Karwin

2
Aynı sorun normal olmayan ilişkisel veritabanı için de mevcuttur.
Bill Karwin

5

CouchDB yaklaşımı, harita aşamasında uygun malzeme sınıflarını yayınlamayı ve bunları azaltarak özetlemeyi önerir. Böylece 1verilen kullanıcı için tüm yorumları ve yayımları haritalayabilir ve daha sonra yalnızca bir tanesini yazdırabilirsiniz. Bununla birlikte, couchDB'deki tüm izlenebilir verilerin kalıcı görünümlerini oluşturmak için çok sayıda disk depolama alanı gerekir. btw ayrıca ilişkilerle ilgili şu wiki sayfasına da sahipler: http://wiki.apache.org/couchdb/EntityRelationship .

Riak ise ilişki kurma araçlarına sahiptir. Bu bağlantıdır. Bağlantılı (burada yorum) bir belgenin adresini 'kök' belgeye (burada kullanıcı belgesine) girebilirsiniz. Bir numarası var. Dağıtılması halinde, birçok yerde tek seferde değiştirilebilir. Çatışmalara neden olacak ve sonuç olarak büyük vektör saat ağacı: / .. o kadar da kötü değil, çok iyi değil.

Riak ayrıca başka bir 'mekanizmaya' sahiptir. Paket ve anahtar adı verilen 2 katmanlı anahtar adı alanına sahiptir. Öyleyse, öğrenci örneği için, A, B ve C kulübümüz ve StudentX, StudentY öğrencimiz varsa, aşağıdaki kuralı sürdürebilirsiniz:

{ Key = {ClubA, StudentX}, Value = true }, 
{ Key = {ClubB, StudentX}, Value = true }, 
{ Key = {ClubA, StudentY}, Value = true }

ve ilişkiyi okumak için sadece verilen kovalardaki anahtarları listeleyin. Bunun derdi ne? Çok yavaş. Riak için listeleme paketleri hiçbir zaman öncelikli olmadı. Giderek daha iyi hale geliyor tho. Btw. Hafızayı boşa harcamazsınız çünkü bu örnek {true}StudentX veya Y'nin tek bir tam profiline bağlanabilir (burada çatışmalar mümkün değildir).

Gördüğünüz gibi NoSQL! = NoSQL. Spesifik uygulamaya bakmanız ve kendiniz için test etmeniz gerekir.

Sütun depolarından önce bahsedilmişti ilişkiler için uygun görünüyor .. ama hepsi sizin A ve C ve P ihtiyaçlarınıza bağlıdır;) A'ya ihtiyacınız yoksa ve Peta bayt'tan daha azına sahipseniz bırakın, MySql veya Postgres ile devam edin.

iyi şanslar


1
Riak, LevelDB arka ucunu kullanırken ikincil dizinler için destek ekleyen v1.0'ı kısa süre önce yayınladı. Çok değerli bir özellik.
Jon L.

4
  1. user: userid: comments makul bir yaklaşımdır - bunu, indekslenmemiş sütunlarda sorgulama yapamayacağınız ek gereksinimi ile birlikte SQL'deki bir sütun dizininin eşdeğeri olarak düşünün.

  2. İhtiyaçlarınızı düşünmeniz gereken yer burasıdır. 30 milyon maddelik bir liste, yavaş olduğu için mantıksız değil, onunla bir şey yapmak pratik olmadığı için. Gerçek gereksiniminiz bazı son yorumları görüntülemekse, bir yorum eklendiğinde güncellenen çok kısa bir liste tutmanız daha iyi olur - NoSQL'in normalleştirme gereksinimi olmadığını unutmayın. Yarış koşulları, temel bir anahtar değer deposundaki listelerle ilgili bir sorundur, ancak genellikle platformunuz listeleri doğru şekilde destekler, kilitlerle bir şeyler yapabilirsiniz veya başarısız güncellemeleri gerçekten önemsemezsiniz.

  3. Kullanıcı yorumlarıyla aynı - bir dizin anahtar sözcüğü oluşturun: gönderiler

  4. Aynı şey - muhtemelen bir öğrenci mülkü olarak kulüplerin bir listesi ve bir kulübün tüm üyelerini almak için bu alandaki bir dizin


Yani, temelde her şeyin sadece listelere ihtiyacı var mı? Kimlik dizilerini manuel olarak takip etmekten daha karmaşık bir yaklaşım olması gerektiği gibi görünüyor. Birincisi, yararlı olmak için yalnızca büyüyene kadar gidebilirsiniz. Sonra tekrar, NoSQL teknolojisinin ana poster çocuk projelerinin (MongoDB, CouchDB, Membase, vb.) Hepsi yeni projelerdir, bu yüzden belki de ilişkileri izlemek için daha iyi bir yol bulmaları için onlara daha fazla zaman vermem gerekiyor.
Xeoncross

NoSQL (AKA ilişkisel olmayan veri depoları) kullanıyorsanız ilişkisel terimlerle düşünmeyi bırakmanız gerekir. Kullanılan yaklaşım platformlar arasında farklılık gösterecektir, ancak dizinleri yönetmeniz gerektiğine dair temel fikir oldukça evrenseldir. Verdiğiniz ilişki örnekleri, NoSQL'de iki farklı şekilde modellenmiştir: 1) Depolama - SQL'den farklı olarak, sütunlar birden çok / karmaşık değere sahip olabilir, bu nedenle alt nesne, ana nesnenin yalnızca bir parçasıdır. 2) Arama - Uzun listeleriniz aslında aranabilirlik için bir gerekliliktir, bu da indeksleme anlamına gelir - basit bir özel liste veya daha eksiksiz bir arama motoru kullanabilirsiniz.
Tom Clarkson

2

Var

"user": {
    "userid": "unique value",
    "category": "student",
    "metainfo": "yada yada yada",
    "clubs": ["archery", "kendo"]
}

"comments": {
    "commentid": "unique value",
    "pageid": "unique value",
    "post-time": "ISO Date",
    "userid": "OP id -> THIS IS IMPORTANT"
}

"page": {
    "pageid": "unique value",
    "post-time": "ISO Date",
    "op-id": "user id",
    "tag": ["abc", "zxcv", "qwer"]
}

İlişkisel bir veri tabanında yapılacak normal şey, bire çok ilişkisinde verileri normalize etmektir. Bu, bir NoSQL veritabanında da yapacağınız şeyin aynısıdır. Bilgiyi getireceğiniz alanları indekslemeniz yeterlidir.

Örneğin, sizin için önemli dizinler

  • Comment.UserID
  • Comment.PageID
  • Comment.PostTime
  • Page.Tag []

Eğer kullanıyorsanız NosDB (SQL desteği ile bir .NET tabanlı NoSQL veritabanı) sorgularınız gibi olacak

 SELECT * FROM Comments WHERE userid = That user’;

 SELECT * FROM Comments WHERE pageid = That user’;

 SELECT * FROM Comments WHERE post-time > DateTime('2016, 1, 1');

 SELECT * FROM Page WHERE tag = 'kendo'

Desteklenen tüm sorgu türlerini SQL hile sayfalarından veya belgelerinden kontrol edin.

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.