हाय / लो एल्गोरिथ्म क्या है?


464

हाय / लो एल्गोरिथ्म क्या है?

मैंने इसे NHibernate दस्तावेज़ीकरण में पाया है (यह अद्वितीय कुंजी उत्पन्न करने के लिए एक विधि है, खंड 5.1.4.2), लेकिन मुझे यह कैसे काम करता है इसका अच्छा विवरण नहीं मिला है।

मुझे पता है कि निबर्नेट इसे संभालता है, और मुझे अंदर जानने की जरूरत नहीं है, लेकिन मैं सिर्फ उत्सुक हूं।

जवाबों:


540

मूल विचार यह है कि प्राथमिक कुंजी बनाने के लिए आपके पास दो नंबर हैं- एक "उच्च" संख्या और एक "कम" संख्या। एक क्लाइंट मूल रूप से "उच्च" अनुक्रम को बढ़ा सकता है, यह जानकर कि यह "निम्न" मानों की विविधता के साथ पिछले "उच्च" मान की संपूर्ण सीमा से सुरक्षित रूप से कुंजी उत्पन्न कर सकता है।

उदाहरण के लिए, मान लीजिए कि आपके पास "उच्च" क्रम 35 के वर्तमान मूल्य के साथ है, और "कम" संख्या 0-1023 की सीमा में है। फिर क्लाइंट 36 तक अनुक्रम को बढ़ा सकता है (अन्य ग्राहकों के लिए 35 का उपयोग करते समय चाबियाँ उत्पन्न करने में सक्षम होने के लिए) और पता है कि चाबियाँ 35/0, 35/1, 35/2, 35/3 ... 35/1023 हैं सभी उपलब्ध।

यह बहुत उपयोगी हो सकता है (विशेष रूप से ओआरएम के साथ) प्राथमिक कुंजी के बिना मूल्यों को सम्मिलित करने के बजाय क्लाइंट कुंजी पर प्राथमिक कुंजी सेट करने में सक्षम होने के लिए और फिर उन्हें क्लाइंट पर वापस लाने के लिए। किसी भी अन्य चीज़ के अलावा, इसका मतलब है कि आप आसानी से माता-पिता / बच्चे के रिश्ते बना सकते हैं और किसी भी आवेषण को करने से पहले आपके पास सभी चाबियाँ हैं , जो उन्हें बैचिंग को सरल बनाता है।


14
क्या आप कह रहे हैं कि "कम रेंज" को ग्राहक के भीतर समन्वित किया जाता है, जबकि "उच्च अनुक्रम" एक DB अनुक्रम से मेल खाता है?
क्रिस नू

14
क्या हाय और लो वैल्यूज़ आम तौर पर एक ही पूर्णांक मूल्य में, या दो-भाग व्यापार कुंजी के रूप में तैयार होते हैं?
क्रिस नॉ

51
एक IP पते की तरह तब - ICANN आपको एक उच्च 'नेटवर्क' नंबर देता है, फिर आपके पास जितने कम CIDR रेंज आपको दिए जाते हैं, उतने कम 'होस्ट' नंबर मिलते हैं।
gbjbaanb

6
@ एडाम: मौलिक रूप से, कुछ भी नहीं - यह केवल कुंजी का एक गुच्छा उत्पन्न करने की तुलना में एक मूल्य ("उच्च" भाग) बढ़ाने के लिए सस्ता है। (यह डेटा ट्रांसफर के मामले में संभावित रूप से बहुत सस्ता है - आप न्यूनतम बैंडविड्थ के साथ बड़ी संख्या में कुंजियों को "आरक्षित" कर सकते हैं।)
जॉन स्कीट

4
@ एडडम: यह सच है अगर चाबियाँ सिर्फ नंबर हैं। GUIDs के लिए इतना कुछ नहीं है :) लेकिन हां, सरल संख्या के मामले में, कोई भी परमाणु "एक निश्चित राशि से वृद्धि" करेगा। यह प्रभावी रूप से हाय-लो क्या कर रहा है, अगर आप इसे एक संख्या के रूप में दो वर्गों में विभाजित करते हैं।
जॉन स्कीट

157

जॉन के जवाब के अलावा:

यह डिस्कनेक्ट किए गए कार्य करने में सक्षम होने के लिए उपयोग किया जाता है। एक क्लाइंट तब सर्वर से एक ही नंबर के लिए पूछ सकता है और खुद ही लो नंबर बढ़ाता हुआ ऑब्जेक्ट बना सकता है। जब तक लो रेंज का उपयोग नहीं किया जाता है तब तक इसे सर्वर से संपर्क करने की आवश्यकता नहीं होती है।


1
मैं इसे संक्षिप्तता के लिए पसंद करता हूं।
डेवलपर Marius ėilėnas

34

चूंकि यह एक बहुत ही सामान्य प्रश्न है, इसलिए मैंने यह लेख लिखा है , जिस पर यह उत्तर आधारित है।

हाय / लो एल्गोरिदम अनुक्रम डोमेन को "हाय" समूहों में विभाजित करता है। "हाय" मान को समकालिक रूप से सौंपा गया है। प्रत्येक "हाय" समूह को "लो" प्रविष्टियों की अधिकतम संख्या दी जाती है, जो समवर्ती डुप्लिकेट प्रविष्टियों के बारे में चिंता किए बिना ऑफ-लाइन असाइन कर सकते हैं।

  1. "हाय" टोकन को डेटाबेस द्वारा सौंपा गया है, और दो समवर्ती कॉलों को अद्वितीय निरंतर मूल्यों को देखने की गारंटी है
  2. "हाय" टोकन प्राप्त होने के बाद हमें केवल "इंक्रीमेंटसाइज" ("लो" प्रविष्टियों की संख्या) की आवश्यकता होती है
  3. पहचानकर्ता सीमा निम्न सूत्र द्वारा दी गई है:

    [(hi -1) * incrementSize) + 1, (hi * incrementSize) + 1)

    और "लो" मान रेंज में होगा:

    [0, incrementSize)

    के प्रारंभ मूल्य से लागू किया जा रहा है:

    [(hi -1) * incrementSize) + 1)
  4. जब सभी "लो" मानों का उपयोग किया जाता है, तो एक नया "हाय" मान प्राप्त किया जाता है और चक्र जारी रहता है

आप इस लेख में अधिक विस्तृत विवरण पा सकते हैं :

और इस दृश्य प्रस्तुति का अनुसरण करना आसान है:

यहाँ छवि विवरण दर्ज करें

हालांकि, हाय / लो ऑप्टिमाइज़र पहचानकर्ता पीढ़ी को अनुकूलित करने के लिए ठीक है, यह हमारी पहचानकर्ता रणनीति के बारे में कुछ भी जानने के बिना, हमारे डेटाबेस में पंक्तियाँ डालने वाली अन्य प्रणालियों के साथ अच्छा नहीं खेलता है।

हाइबरनेट, पूलेड-लो ऑप्टिमाइज़र प्रदान करता है, जो अन्य 3-पक्ष क्लाइंट के साथ इंटरऑपरेबिलिटी प्रदान करते हुए हाय / लो जनरेटर रणनीति के फायदे प्रदान करता है जो इस अनुक्रम आवंटन रणनीति के बारे में नहीं जानते हैं।

अन्य प्रणालियों के साथ कुशल और इंटरऑपरेबल होने के नाते, पूलेड-लो ऑप्टिमाइज़र विरासत की तुलना में बहुत बेहतर उम्मीदवार है / लो राइटर रणनीति।


मैं वास्तव में आपको कभी-कभी समझ नहीं पा रहा हूं इसलिए: हालांकि हाय / लो ऑप्टिमाइज़र पहचानकर्ता पीढ़ी (ओके अच्छा) के अनुकूलन के लिए ठीक है, यह अन्य प्रणालियों के साथ अच्छा नहीं खेलता है (अन्य प्रणालियों से आपका क्या मतलब है?), जो पहले हैं हमारे डेटाबेस में पंक्तियाँ डालना? (हमारी पहचान की रणनीति के बारे में कुछ भी जाने बिना, पंक्तियों को सम्मिलित करने के लिए प्रयुक्त पहचानकर्ता पीढ़ी?)।
एडेलिन

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

यदि आपका उत्तर आपके उत्तर के लिए उपयुक्त नहीं है तो मेरी क्षमा याचना, लेकिन मैं सोच रहा था कि डिफ़ॉल्ट रूप से क्या अनुकूलक का उपयोग किया जाता है? या यह DB पर निर्भर करता है (मैं PostgreSQL का उपयोग कर रहा हूं)? क्योंकि मैं वर्तमान अनुक्रम मान और उत्पन्न आईडी के बीच संबंध का पता नहीं लगा सकता। मैं @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "name") @SequenceGenerator(name="name", sequenceName = "name_seq", allocationSize=100)अपनी आईडी के लिए उपयोग कर रहा हूं ।
स्टीफन गोलूबोविक

1
5 हाइबरनेट के बाद से, नया हाय / लो नहीं, बल्कि नया ऑप्टिमाइज़र है। की जाँच करें अधिक जानकारी के लिए इस लेख जमा अनुकूलक के बारे में।
व्लाद मिहालसी

@VladMihalcea, मेरा मानना ​​है कि आपके पास बुलेट तीन में एक टाइपो है, पहले स्निपेट पर , (hi * incrementSize) + 1)... यह , hi * incrementSize)सही होना चाहिए ?
हियुगन

23

लो एक कैश्ड एलोकेटर है जो कीस्पेस को बड़ी मात्रा में विभाजित करता है, जो आमतौर पर सार्थक आकार की सीमाओं (जैसे एक समय में 200 कुंजी प्राप्त करना) के बजाय कुछ मशीन शब्द के आकार पर आधारित होता है, जिसे मानव समझदारी से चुन सकता है।

हाई-लो उपयोग सर्वर पुनरारंभ पर बड़ी संख्या में कुंजियों को बर्बाद करने और बड़े मानव-प्रमुख कुंजी मान उत्पन्न करता है।

हाय-लो आवंटनकर्ता की तुलना में बेहतर, "रैखिक चंक" आवंटनकर्ता है। यह एक समान तालिका-आधारित सिद्धांत का उपयोग करता है, लेकिन छोटे, आसानी से आकार के आकार को आवंटित करता है और अच्छे मानव-अनुकूल मूल्य उत्पन्न करता है।

create table KEY_ALLOC (
    SEQ varchar(32) not null,
    NEXT bigint not null,
    primary key (SEQ)
);

अगला, आवंटित करने के लिए, 200 कुंजियाँ (जो तब सर्वर में एक श्रेणी के रूप में रखी जाती हैं और आवश्यकतानुसार उपयोग की जाती हैं):

select NEXT from KEY_ALLOC where SEQ=?;
update KEY_ALLOC set NEXT=(old value+200) where SEQ=? and NEXT=(old value);

आप इस लेनदेन को प्रदान कर सकते हैं (विवाद को संभालने के लिए पुनर्प्रयास का उपयोग करें), आपने 200 कुंजी आवंटित की हैं और आवश्यकतानुसार उन्हें निकाल सकते हैं।

सिर्फ 20 के एक चंक-आकार के साथ, यह योजना ओरेकल अनुक्रम से आवंटित करने की तुलना में 10 गुना तेज है, और सभी डेटाबेस के बीच 100% पोर्टेबल है। आवंटन प्रदर्शन हाय-लो के बराबर है।

एंबलर के विचार के विपरीत, यह कुंजी क्षेत्र को एक सन्निहित रैखिक संख्या के रूप में मानता है।

यह कम्पोज़िट कुंजियों के लिए आवेग से बचा जाता है (जो कि वास्तव में एक अच्छा विचार नहीं था) और सर्वर के पुनरारंभ होने पर पूरे लो-वर्ड को बर्बाद करने से बचा जाता है। यह "मैत्रीपूर्ण", मानव-स्तर के प्रमुख मूल्यों को उत्पन्न करता है।

श्री अम्बलर का विचार, तुलनात्मक रूप से, उच्च 16- या 32-बिट्स को आवंटित करता है, और बड़े मानव-अमित्र प्रमुख मूल्यों को हाय-शब्द वृद्धि के रूप में उत्पन्न करता है।

आवंटित कुंजियों की तुलना:

Linear_Chunk       Hi_Lo
100                65536
101                65537
102                65538
.. server restart
120                131072
121                131073
122                131073
.. server restart
140                196608

डिज़ाइन-वार, उसका समाधान मौलिक रूप से संख्या-लाइन (समग्र कुंजियों, बड़े hi_word उत्पादों) पर रैखिक तुलना में अधिक जटिल है, जबकि कोई तुलनात्मक लाभ प्राप्त नहीं हुआ है।

हाय-लो डिज़ाइन OO मैपिंग और हठ में जल्दी पैदा हुआ। इन दिनों हाइबरनेट जैसी दृढ़ता रूपरेखा उनके डिफ़ॉल्ट के रूप में सरल और बेहतर आवंटन प्रदान करती है।


4
अच्छी पोस्ट है, लेकिन आप सवाल का जवाब नहीं दे रहे हैं।
कक्षीय

1
एक दिलचस्प जवाब के लिए +1। मैं सहमत हूं कि सरल दृष्टिकोण पर हाय-लो से किसी भी प्रकार का अधिक लाभ नहीं मिलता है; हालाँकि, मुझे लगता है कि उच्च-समवर्ती अनुप्रयोगों में कई आवंटनकर्ताओं के विशेष मामले के लिए हाय-लो बेहतर अनुकूल है।
ऋचज

1
थैंक्स @richj! मेरा कहना है कि आप "रैखिक ब्लॉक आवंटन" के साथ कई आवंटनकर्ता या बड़े ब्लॉक आकार का उपयोग कर सकते हैं, लेकिन वह - हाय / लो के विपरीत - यह तालिका में चाबियों के लिए आवंटितकर्ता NEXT_VAL का एक रैखिक पत्राचार रखता है , और ट्यूनेबल है। HiLo के विपरीत, किसी गुणन की आवश्यकता नहीं है - यह आवश्यक नहीं है! NEXT_HI का गुणक और संग्रहण HiLo को अधिक जटिल बनाता है और विखंडन को तोड़ता है, क्योंकि अवरोधन बदलने से मनमाने ढंग से जारी की जाने वाली अगली कुंजी बदल जाएगी .. देखें: literatejava.com/hibernate/…
थॉमस W

2
मुझे कई स्वतंत्र आवंटनकर्ताओं में दिलचस्पी है। हाय-लो के साथ यह स्पष्ट है कि उच्च मूल्य को आवंटनकर्ता आईडी / ब्लॉक आईडी में विभाजित किया जा सकता है। यह तुरंत (मेरे लिए) स्पष्ट नहीं था कि एक ही दृष्टिकोण रैखिक चंक पर लागू किया जा सकता है, लेकिन यह मूल रूप से आवंटनकर्ताओं के बीच कुल सीमा को विभाजित करने की समान समस्या है। मुझे अब मिल गया है। धन्यवाद।
रिचज

1
ओह, इसके बारे में सोचने के बाद, मुझे लगता है कि एसईक्यू कॉलम कॉलम टेबल के नाम पर है। उदाहरण के लिए, ग्राहक तालिका, आदेश तालिका के लिए एक, और इसके बाद के संस्करण में एक आबंटक है। मुझे माफ कर दो, मैं कभी-कभी धीमे हो जाता हूं।
रॉक एंथनी जॉनसन

1

मैंने पाया कि हाय / लो एल्गोरिथ्म मेरे अनुभव के आधार पर प्रतिकृति परिदृश्यों के साथ कई डेटाबेस के लिए एकदम सही है। इसकी कल्पना करें। आपके पास न्यूयॉर्क में एक सर्वर (उर्फ 01) और लॉस एंजिल्स में एक और सर्वर (उर्फ 02) है, तो आपके पास एक व्यक्तिगत तालिका है ... इसलिए न्यूयॉर्क में जब कोई व्यक्ति बनाता है ... तो आप हमेशा 01 मान के रूप में उपयोग करते हैं। और एलओ मान अगले सेक्युलर है। उदाहरण

  • 010000010 जेसन
  • 010000011 डेविड
  • 010000012 थियो

लॉस एंजिल्स में आप हमेशा HI 02 का उपयोग करते हैं। उदाहरण के लिए:

  • 020000045 रुपए
  • 020000046 ओसवाल्ड
  • 020000047 मारियो

इसलिए, जब आप डेटाबेस की प्रतिकृति का उपयोग करते हैं (कोई फर्क नहीं पड़ता कि कौन सा ब्रांड) सभी प्राथमिक कुंजी और डेटा आसानी से और स्वाभाविक रूप से डुप्लिकेट प्राथमिक कुंजियों, टकरावों आदि के बारे में चिंता किए बिना।

इस परिदृश्य में जाने का यह सबसे अच्छा तरीका है।


यह हाइबरनेट में काम नहीं करता है। HiLo अल्ग्रोटर्म को प्रत्येक लेनदेन में अनुक्रम का एक नया मूल्य मिलता है, इसलिए HI-काउंटर वेतन वृद्धि के आधार पर। लेकिन आपके उदाहरण में, HI-काउंटर हमेशा एक DB के लिए स्थिर रहता है।
दिमित्री 1405
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.