इन-मेमोरी इंडेक्स के लिए अच्छा स्नैपशॉटेबल डेटा स्ट्रक्चर


12

मैं एक बहुत विशिष्ट उपयोग के मामले में इन-मेमोरी ऑब्जेक्ट डेटाबेस डिज़ाइन कर रहा हूं। यह एकल लेखक है, लेकिन कुशल समवर्ती पठन का समर्थन करना चाहिए। रीड्स को अलग किया जाना चाहिए। कोई क्वेरी भाषा नहीं है, डेटाबेस केवल समर्थन करता है:

  • ऑब्जेक्ट / -s को विशेषता के आधार पर / विशेषताओं के सेट (अभिव्यक्ति के लिए समर्थन हो सकता है, उदाहरण के लिए x.count < 5)
  • ऑब्जेक्ट की विशेषता प्राप्त करें

एक क्वेरी एक अनिवार्य स्क्रिप्ट है जो उपरोक्त कार्यों की एक मनमानी संख्या से बना है। डेटा का आकार << मेमोरी होगा, इसलिए अधिकांश विशेषताओं पर सभी ऑब्जेक्ट और सूचकांकों को स्वैप किए बिना आराम से फिट होना चाहिए।

मुझे ऑब्जेक्ट की विशेषता इंडेक्स के लिए एक डेटा संरचना की आवश्यकता है, जो लिखने पर O (n) हो सकता है, लेखन संगति का समर्थन नहीं कर सकता, लेकिन आदर्श रूप से O (1) स्नैपशॉट (शायद लिखने पर कॉपी) और O (logN) एक्सेस का समर्थन करना चाहिए। आदर्श रूप से यह संस्करणों के बीच अधिकतम संरचनात्मक साझाकरण के साथ रीड्स पर उच्च संगामिति की अनुमति देगा।

मैं CTries , समवर्ती BSTs और समवर्ती Splay पेड़ देख रहा था , लेकिन मुझे यकीन नहीं है कि मैं वास्तव में यहाँ सही दिशा में देख रहा हूँ। उपरोक्त संरचना आवेषण की जटिलता पर बहुत ध्यान देती है जिसके बारे में मुझे परवाह नहीं है।

प्रश्न : क्या कोई ज्ञात डेटा संरचना है जो बॉक्स के बाहर मेरे उपयोग के मामले के लिए एक अच्छा फिट है?

EDIT : कुछ और सोचने के बाद ऐसा लगता है कि लगातार BST / Splay ट्री काम करेगा। लेखक 'मास्टर' कॉपी को अपडेट करेगा और प्रश्नों के निष्पादन की शुरुआत के रूप में पेड़ को प्राप्त करेगा और उन्हें पूरा करने के बाद इसे फेंक देगा। हालाँकि, मैं अभी भी दिलचस्पी रखता हूँ अगर वहाँ एक बेहतर समाधान है।


1
क्या आपको मेमोरी में स्नैपशॉट की आवश्यकता है, या क्या आपको उन्हें डिस्क / नेटवर्क पर सहेजने की आवश्यकता है? विशुद्ध रूप से कार्यात्मक डेटा संरचना स्वचालित रूप से आपको इन-मेमोरी स्नैपशॉट देती है, इसलिए यदि आपको इसकी आवश्यकता है, तो यह आपकी सबसे अच्छी शर्त है।
गिल्स एसओ- बुराई को रोकना '

यह सब स्मृति में है। मैं सोच रहा था कि शायद एक निरंतर-समय के स्नैपशॉट के साथ एक कुशल परिवर्तनशील संस्करण है (जैसे कि सेरी, केवल समवर्ती लेखन के बिना)।
dm3

2
आपकी समस्या डेटा संरचना की पसंद कम हो सकती है, लेकिन समवर्ती नियंत्रण की तरह।
राफेल

यह अच्छी तरह से हो सकता है, क्या आप उस पर थोड़ा और विस्तार कर सकते हैं?
dm3

जवाबों:


5

किसी भी तरह के लगातार / अपरिवर्तनीय (यानी, कार्यात्मक) पेड़-आधारित डेटा संरचना का उपयोग करें। कुंजी को लॉकिंग राइट मिल रहा है, जैसा कि @ राफेल ने टिप्पणियों में बताया है।

कार्यात्मक / लगातार पेड़-आधारित डेटा संरचनाओं के बारे में अच्छी बात यह है कि आपको मुफ्त में "स्नैपशॉट" मिलते हैं। मान लीजिए कि आप अपने डेटा संरचना के लिए एक ट्रेप (यादृच्छिक बाइनरी खोज ट्री) का उपयोग करते हैं। यहाँ गो: https://github.com/steveyen/gtreap में लिखा गया एक उदाहरण है । लेखक इसका वर्णन इस प्रकार करता है:

अपरिवर्तनीय करके, किसी treap के लिए कोई भी अपडेट / डिलीट एक नया treap लौटाएगा जो पिछले treap के साथ आंतरिक नोड्स साझा कर सकता है। इस कार्यान्वयन में सभी नोड्स उनके निर्माण के बाद ही पढ़े जाते हैं। यह समवर्ती पाठकों को समवर्ती लेखकों के साथ सुरक्षित रूप से संचालित करने की अनुमति देता है क्योंकि संशोधन केवल नई डेटा संरचनाएं बनाते हैं और मौजूदा डेटा संरचनाओं को कभी भी संशोधित नहीं करते हैं। यह MVCC या मल्टी-वर्जन कंसीडर कंट्रोल को प्राप्त करने का एक सरल तरीका है।

O(logn)

आप पॉइंटर को रूट की सुरक्षा के लिए लॉक का उपयोग करते हैं। चूंकि डेटा संरचना अपरिवर्तनीय है पठन को समवर्ती रूप से किया जा सकता है, और आप पुराने स्नैपशॉट को संकेत बचा सकते हैं। एक पढ़ा है:

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

भले ही खोज में थोड़ा समय लग सकता है, आप केवल पॉइंटर की प्रतिलिपि बनाते समय लॉक को पकड़ते हैं, इसलिए खोज समवर्ती हो सकती हैं।

एक लेखन है:

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

इस संस्करण में, लिखते हैं कि पेड़ के नए संस्करण को बनाने की पूरी प्रक्रिया के दौरान लॉक को रखने की आवश्यकता है। आप पढ़ने के प्रदर्शन को बेहतर बना सकते हैं (कभी-कभी लेखन लेनदेन विफल होने की कीमत पर) लेखन को कुछ इस तरह से बदलकर:

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

यदि आपकी प्रोग्रामिंग भाषा में परमाणु तुलना-और-स्वैप ऑपरेशन के साथ परमाणु चर हैं, तो आप थोड़ा बेहतर भी कर सकते हैं (इसे "लॉक फ्री" बना सकते हैं)। (उदाहरण के लिए C ++ 11 का उपयोग करके atomic<T*>।)


विस्तृत जवाब के लिए धन्यवाद। मुझे इस तरह का पता था, शायद मैंने सवाल में ही इतना स्पष्ट रूप से नहीं डाला। हालाँकि, जवाब अभी भी महान है!
dm3

आपका "बेहतर" संस्करण उपयोग में सिस्टम के मेमोरी मॉडल पर निर्भर करता है। यह अच्छी तरह से कुछ सिस्टम पर अस्थिर घोषित किए जाने के लिए क्रियाओं की आवश्यकता हो सकती है और कोडिंग को सही करने के लिए महान कौशल की आवश्यकता होती है।
इयान रिंगरोज

1

Microsoft ने मेमोरी डेटाबेस में अपने नए पर विवरण प्रकाशित किया है, इसमें ऐसे इंडेक्स हैं जो लिखते समय रीड को ब्लॉक नहीं करते हैं।

उदाहरण के लिए:

जस्टिन लेवांडोस्की, डेविड लोमेट, और सुदीप्ता सेनगुप्ता, द बी-ट्री: ए बी-ट्री फॉर न्यू हार्डवेयर, 2013 में आईईईई 29 वें इंटरनेशनल कॉन्फ्रेंस ऑन डेटा इंजीनियरिंग (आईसीडीई), इंटरनेशनल कॉन्फ्रेंस ऑन डेटा इंजीनियरिंग, 8 नवंबर 2013।

उनके प्रकाशनों की सूची के लिए http://research.microsoft.com/en-us/projects/main-memory_dbs/ देखें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.