Bellek içi bir dizin için iyi anlık görüntü yapısı


12

Çok özel bir kullanım durumu için bir bellek içi nesne veritabanı tasarlıyorum. Tek bir yazardır, ancak verimli eşzamanlı okumaları desteklemesi gerekir. Okumalar izole edilmelidir. Sorgu dili yoktur, veritabanı yalnızca şunları destekler:

  • özniteliğe / öznitelik kümesine göre nesne / -s alma (ifadeler için destek olabilir, ör. x.count < 5)
  • nesnenin niteliğini al

Sorgu, yukarıdaki işlemlerden rasgele bir sayıdan oluşan zorunlu bir komut dosyasıdır. Veri boyutu << bellek olacaktır, bu nedenle özelliklerin çoğundaki tüm nesne ve indeksler değiştirilmeden rahatça sığmalıdır.

Ne ihtiyacım var yazma nesneler, yazma eşzamanlılık desteklemiyor, ancak ideal O (1) anlık görüntüleri (belki yazma üzerine kopya) ve O (logN) erişimi desteklemelidir nesnenin öznitelik dizini için bir veri yapısıdır. İdeal olarak, sürümler arasında maksimum yapısal paylaşım ile okumalarda yüksek eşzamanlılığa izin verir.

Ben bakıyordum CTries , Eşzamanlı BSTS ve Eşzamanlı Splay Ağaçlar ama gerçekten burada doğru yönde arıyorum olmadığından emin değilim. Yukarıdaki yapılar, umursamadığım eklerin karmaşıklığına çok dikkat ediyor.

Soru : Kullanım durumum için kutudan çıktığı bilinen bir veri yapısı var mı?

EDIT : biraz düşündükten sonra kalıcı bir BST / Splay ağacı işe yarayacak gibi görünüyor. Yazar, 'ana' kopyayı güncelleyecek ve sorgular yürütme başlangıcından itibaren ağacı alacak ve bittikten sonra onu atacaktı. Ancak, daha iyi bir çözüm olup olmadığı konusunda hala ilgileniyorum.


1
Bellekte anlık görüntülere mi ihtiyacınız var, yoksa bunları diske / ağa mı kaydetmeniz gerekiyor? Tamamen işlevsel bir veri yapısı size otomatik olarak bellek içi anlık görüntüler verir, bu yüzden ihtiyacınız olan şey buysa, en iyi seçimdir.
Gilles 'SO- kötü olmayı bırak

Hepsi hafızada. Belki de sabit zamanlı bir anlık görüntü (CTrie gibi, sadece eşzamanlı yazma olmadan) ile verimli bir değişebilir versiyonu olduğunu merak ediyordum.
dm3

2
Sorununuz veri yapısı seçiminin daha az olması, ancak eşzamanlılık kontrolünün türü olabilir.
Raphael

Belki biraz daha fazla ayrıntı verebilir misiniz?
dm3

Yanıtlar:


5

Her türlü kalıcı / değişmez (yani, işlevsel) ağaç tabanlı veri yapısı kullanın. @Raphael yorumlarda belirttiği gibi, kilit kilitlemeyi doğru yapmaktır.

İşlevsel / kalıcı ağaç tabanlı veri yapıları ile ilgili güzel bir şey, "anlık görüntüler" elde etmenizdir. Diyelim ki veri yapınız için bir ikram (rastgele ikili arama ağacı) kullandınız. İşte Go'da yazılmış bir örnek: https://github.com/steveyen/gtreap . Yazar bunu şöyle açıklar:

Değişmez olarak, bir tedaviye yapılan tüm güncellemeler / silmeler, dahili düğümleri önceki işlem ile paylaşabilecek yeni bir işlem döndürür. Bu uygulamadaki tüm düğümler oluşturulduktan sonra salt okunurdur. Bu, eşzamanlı okuyucuların eşzamanlı yazarlarla güvenli bir şekilde çalışmasına izin verir, çünkü değişiklikler sadece yeni veri yapıları oluşturur ve mevcut veri yapılarını asla değiştirmez. Bu, MVCC veya çok versiyonlu eşzamanlılık kontrolü elde etmek için basit bir yaklaşımdır.

O(logn)

İşaretçiyi köke korumak için bir kilit kullanın. Veri yapısı değişmez olduğu için okumalar eşzamanlı olarak yapılabilir ve eski anlık görüntülere işaretçiler kaydedebilirsiniz. Bir okuma:

lock
tmp = ptr_to_root
unlock
value = search(tmp, <value to search for>)
return value

Arama biraz zaman alsa da, kilidi yalnızca işaretçiyi kopyalarken basılı tutarsınız, böylece aramalar aynı anda yapılabilir.

Bir yazma:

lock
old_ptr_to_root = ptr_to_root
ptr_to_root = insert(old_ptr_to_root, <new key/value pair>)
unlock

Bu sürümde, yazma işlemlerinin ağacın yeni sürümünü oluşturma işlemi boyunca kilidi tutması gerekir. Yazmayı aşağıdaki gibi değiştirerek okuma performansını artırabilirsiniz (bazen yazma işleminin başarısız olması pahasına):

top:
  lock
  old_ptr_to_root = ptr_to_root
  unlock
  new_ptr_to_root = insert(old_ptr_to_root, <new key/value pair>)
  lock
  if (ptr_to_root == old_ptr_to_root)   # make sure no other write happened in the interim
    ptr_to_root = new_ptr_to_root
    unlock
  else                                  # transaction fails, try again
    unlock
    goto top

Programlama dilinizde atomik bir karşılaştırma ve değiştirme işlemi olan atom değişkenleri varsa, biraz daha iyi yapabilirsiniz ("kilitlemeyin"). (Örneğin C ++ 11 kullanarak atomic<T*>.)


Ayrıntılı cevap için teşekkürler. Bunu belki biliyordum, belki de sorunun kendisine yeterince açık bir şekilde koymadım. Ancak, cevap hala harika!
dm3

"Geliştirilmiş" sürümünüz, kullanılan sistemin bellek modeline bağlıdır. Bazı sistemlerde geçici olarak ilan edilmesi verable'lara ihtiyaç olabilir ve kodlamanın doğru olması için büyük beceriye ihtiyaç duyabilir.
Ian Ringrose

1

Microsoft bellek veritabanındaki yeni ayrıntılarını yayınladı, yazma işlemi sırasında okumaları engellemeyen dizinlere sahip.

Örneğin:

Justin Levandoski, David Lomet ve Sudipta Sengupta, The Bw-Tree: Yeni Donanım İçin Bir B Ağacı, 2013 yılında IEEE 29. Uluslararası Veri Mühendisliği Konferansı (ICDE), Uluslararası Veri Mühendisliği Konferansı, 8 Nisan 2013.

Yayınlarının bir listesi için http://research.microsoft.com/en-us/projects/main-memory_dbs/ adresine bakın .

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.