बड़ी संख्या में डायनमोबीडी से आइटम हटाने का अनुशंसित तरीका क्या है?


111

मैं DynamoDB में एक सरल लॉगिंग सेवा लिख ​​रहा हूं।

मेरे पास एक लॉग टेबल है जो कि user_id हैश और टाइमस्टैम्प (यूनिक्स एपोक इंट) रेंज द्वारा की गई है।

जब सेवा का कोई उपयोगकर्ता अपना खाता समाप्त कर देता है, तो मुझे सीमा मूल्य की परवाह किए बिना तालिका की सभी वस्तुओं को हटाने की आवश्यकता होती है।

इस तरह के ऑपरेशन को करने का अनुशंसित तरीका क्या है (ध्यान में रखते हुए हटाने के लिए लाखों आइटम हो सकते हैं)?

मेरे विकल्प, जहाँ तक मैं देख सकता हूँ:

A: कोई लौटे आइटम नहीं होने तक, प्रत्येक लौटे आइटम पर कॉल हटाने के लिए एक स्कैन ऑपरेशन करें

बी: एक बैच ऑपरेशन निष्पादित करें, फिर से प्रत्येक आइटम पर डिलीट कॉलिंग करें जब तक कि कोई भी न बचा हो

ये दोनों मुझे बहुत भयानक लगते हैं क्योंकि उन्हें एक लंबा समय लगेगा।

क्या मैं आदर्श रूप से करना चाहता हूं कॉल LogTable.DeleteItem (user_id) - सीमा की आपूर्ति के बिना, और यह मेरे लिए सब कुछ हटा दिया है।

जवाबों:


52

क्या मैं आदर्श रूप से करना चाहता हूं कॉल LogTable.DeleteItem (user_id) - सीमा की आपूर्ति के बिना, और यह मेरे लिए सब कुछ हटा दिया है।

वास्तव में एक समझने योग्य अनुरोध; मैं कल्पना कर सकता हूं कि एडब्ल्यूएस टीम द्वारा इन्हें समय के साथ जोड़ा जा सकता है (इनके पास सीमित सुविधा के साथ शुरू करने का इतिहास है और ग्राहकों की प्रतिक्रिया के आधार पर एक्सटेंशन का मूल्यांकन करना है), लेकिन यहाँ है कि आपको क्या करना चाहिए ताकि आप लागत से बच सकें कम से कम एक पूर्ण स्कैन:

  1. के लिए सभी वस्तुओं को पुनः प्राप्त करने के लिए स्कैन के बजाय क्वेरी का उपयोग करें - यह संयुक्त हैश / रेंज के उपयोग में प्राथमिक कुंजी की परवाह किए बिना काम करता है, क्योंकि HashKeyValue और RangeKeyCondition इस API में अलग-अलग पैरामीटर हैं और पूर्व केवल हैश घटक के मान को लक्षित करता है। प्राथमिक कुंजी। user_id

    • कृपया ध्यान दें कि आपको हमेशा की तरह यहाँ क्वेरी API पेजिंग से निपटना होगा, ExclusiveStartKey पैरामीटर देखें:

      आइटम की प्राथमिक कुंजी जिसमें से पहले की क्वेरी जारी रखना है। यदि यह क्वेरी क्वेरी को पूरा करने से पहले बाधित हो जाती है, तो पहले वाली क्वेरी LastEvalookKey के रूप में यह मान प्रदान कर सकती है; या तो परिणाम सेट आकार या सीमा पैरामीटर के कारण। LastEvalittedKey को उस बिंदु से कार्रवाई जारी रखने के लिए एक नए क्वेरी अनुरोध में वापस पारित किया जा सकता है।

  2. सभी लौटी वस्तुओं पर लूप करें और हमेशा की तरह DeleteItem की सुविधा प्रदान करें

    • अपडेट : सबसे अधिक संभावना बैचवाइटम इस तरह के उपयोग के मामले के लिए अधिक उपयुक्त है (विवरण के लिए नीचे देखें)।

अपडेट करें

Ivant द्वारा हाइलाइट किए जाने के बाद , बैचविटइटम ऑपरेशन आपको एक ही एपीआई कॉल [जोर मेरा] में कई तालिकाओं में कई आइटम डालने या हटाने में सक्षम बनाता है :

एक आइटम अपलोड करने के लिए, आप PutItem API का उपयोग कर सकते हैं और एक आइटम को हटाने के लिए, आप DeleteItem API का उपयोग कर सकते हैं। हालाँकि, जब आप बड़ी मात्रा में डेटा अपलोड या डिलीट करना चाहते हैं, जैसे कि बड़ी मात्रा में Amazon Elastic MapReduce (EMR) अपलोड करना या किसी अन्य डेटाबेस से Amazon DynamoDB में डेटा माइग्रेट करना, यह API एक कुशल विकल्प प्रदान करता है।

कृपया ध्यान दें कि इसकी अभी भी कुछ प्रासंगिक सीमाएँ हैं, विशेष रूप से:

  • एक ही अनुरोध में अधिकतम संचालन - आप कुल 25 डाल या परिचालन को हटाने के लिए निर्दिष्ट कर सकते हैं; हालाँकि, कुल अनुरोध का आकार 1 एमबी (HTTP पेलोड) से अधिक नहीं हो सकता है।

  • एक परमाणु ऑपरेशन नहीं - एक बैचविटेम में निर्दिष्ट व्यक्तिगत ऑपरेशन परमाणु हैं; हालांकि BatchWriteItem एक पूरे के रूप में एक "सबसे अच्छा प्रयास" ऑपरेशन है और एक परमाणु ऑपरेशन नहीं है। यह है कि, बैचविट इमिट अनुरोध में, कुछ ऑपरेशन सफल हो सकते हैं और अन्य विफल हो सकते हैं। [...]

फिर भी यह स्पष्ट रूप से हाथ में एक जैसे मामलों के उपयोग के लिए संभावित रूप से महत्वपूर्ण लाभ प्रदान करता है।


4
मुझे लगता है कि दूसरे चरण के लिए बैच हटाने का उपयोग करना समझ में आएगा (यह बैच लिखने के संचालन के रूप में "मुखौटा" है )
ivant

1
@ivant - संकेत के लिए बहुत बहुत धन्यवाद, यह "नकाबपोश" बैचविटाइटेम की कार्यक्षमता को हटा दें; मैंने उसी हिसाब से जवाब अपडेट किया है।
स्टीफन ओपेल

BatchWriteItemवस्तुओं के साथ हटाने के लिए के माध्यम से निर्दिष्ट किया जाना चाहिएTableWriteItems
नील

1
BatchWriteItem का लिंक अब docs.aws.amazon.com/amazondynamodb/latest/APIReference/…
टोनी

3
मुझे लगता है कि यह पुराना है, और ओपी ने एक विशिष्ट भाषा एसडीके का उल्लेख नहीं किया है, लेकिन पायथन batch_writer()में boto3.resource.Tableएपीआई के हिस्से के रूप में एक उच्च स्तर है जो बैचों में "बफ़रिंग और आइटम भेजना" स्वचालित रूप से संभाल लेगा। इसके अलावा, बैच लेखक करेगा। स्वचालित रूप से किसी भी असंसाधित वस्तुओं को संभालें और आवश्यकतानुसार उन्हें फिर से भेजें "यानी यह बैचवेयर के आसपास एक आवरण है जो कष्टप्रद भागों का प्रबंधन करता है। boto3.amazonaws.com/v1/documentation/api/latest/reference/…
दावोस

46

डायनॉम्बि प्रलेखन के अनुसार आप केवल पूर्ण तालिका हटा सकते हैं।

निचे देखो:

"एक-एक करके वस्तुओं को हटाने की तुलना में एक पूरी तालिका को हटा देना काफी अधिक कुशल है, जो अनिवार्य रूप से लिखने के थ्रूपुट को दोगुना कर देता है, जैसे कि आप जितने ऑपरेशन हटाते हैं उतने ऑपरेशन करते हैं"

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

यह है कि आपने एडब्ल्यूएस एसडीके का उपयोग करके जावा में एक टेबल कैसे हटाएं:

DeleteTableRequest deleteTableRequest = new DeleteTableRequest()
  .withTableName(tableName);
DeleteTableResult result = client.deleteTable(deleteTableRequest);

8
मुझे यह उत्तर बहुत पसंद है, लेकिन सावधानी: यह आपके सिस्टम में कई टेबल बना सकता है और हम प्रति टेबल प्रावधान का भुगतान करते हैं। इसलिए, आपको महीने के अंत के बाद प्रावधान को कम करने की आवश्यकता है (यदि आपकी तालिका प्रति माह है), जबकि यह तालिका हटा नहीं है।
सर्जियो एमसी फिगयूरेडो

2
इस उत्तर से सहमत हों, तो यह लागू है यदि आपको सभी रिकॉर्ड को हटाने की आवश्यकता है तो तालिका बनाएं, लेकिन यहां प्रश्नकर्ता संपूर्ण तालिका नहीं बल्कि उपयोगकर्ता आधार प्रविष्टियों को हटाना चाहता है।
इत्शाम मिन्हास

1
प्रत्येक उपयोगकर्ता के लिए एक अलग टेबल टेबल होने से डायनमोबीडी मूल्य निर्धारण महंगा हो जाएगा। प्रति माह एक टेबल वास्तव में चीजों को बदतर बना देगा। यह स्पष्ट रूप से एक अलग, बहुत विशिष्ट समस्या का जवाब है।
एंड्रे वेर्लंग

11
यदि आप अपने टेबल को स्टैक के भाग के रूप में प्रबंधित करने के लिए क्लाउडफ़ॉर्मेशन जैसे स्वचालित प्रावधान का उपयोग करते हैं, तो तालिका को हटाना भी एक आकर्षक विकल्प नहीं हो सकता है। मुझे CloudFormation को एक तालिका बनाने के लिए एक सरल तरीके के बारे में पता नहीं है जिसे आपने हाथ से हटा दिया है।
ब्रेबस्टर

2
यह दृष्टिकोण तालिका को हटाने और पुन: निर्मित करने में बहुत समय लेता है (आवश्यकता होने पर), यह पूरे समय के दौरान अनुपलब्ध होता है। प्रश्न में स्पष्ट रूप से उपयोगकर्ता डेटा को हटाने के लिए कहा गया है, जो अलग-अलग, प्रति-उपयोगकर्ता तालिकाओं में अव्यवहारिक विभाजन होगा।
एन्द्र वेर्लंग

13

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

आपके मामले में, मैं ttl तब जोड़ूंगा जब लॉग समाप्त हो जाएंगे और एक उपयोगकर्ता द्वारा हटाए जाने के बाद उन्हें छोड़ देंगे। TTL सुनिश्चित करेगा कि लॉग को अंततः हटा दिया जाए।

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

डायनेमोबीडी आमतौर पर समयसीमा समाप्त वस्तुओं को समाप्ति के 48 घंटों के भीतर हटा देता है। वह अवधि जिसके भीतर कोई वस्तु वास्तव में समाप्ति के बाद हटा दी जाती है, कार्यभार की प्रकृति और तालिका के आकार के लिए विशिष्ट है। जो आइटम समाप्त हो चुके हैं और हटाए नहीं गए हैं वे अभी भी रीड, क्वेरी और स्कैन में दिखाई देंगे। ये आइटम अभी भी अपडेट किए जा सकते हैं और समाप्ति विशेषता को बदलने या निकालने के लिए सफल अपडेट सम्मानित किए जाएंगे।

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/howitworks-ttl.html


TTL जोड़ना एक "अपडेट" (ऑपरेशन लिखना) है। मुझे यकीन नहीं है कि "डिलीट" के बजाय "अपडेट" करने का कोई लाभ है।
तोमर

आपके पास वह डेटा हो सकता है जो मूल लेखन के साथ डाला गया हो और किसी अन्य अद्यतन कार्रवाई के साथ अपडेट किया गया हो। बेशक, यह एक विकल्प नहीं है यदि आपके पास डेटा का एक गुच्छा है और फिर आप इसे हटाना चाहते हैं। लेकिन यह उन मामलों के लिए एक वैध विकल्प है, जहां आप डेटा डालने या अपडेट करने के लिए ttl कर सकते हैं।
लुकास लीजिस

1
मैं सहमत हूं, अगर पहले से ही टीटीएल कॉन्फ़िगर है और सफाई 48 घंटे तक इंतजार कर सकती है जो निश्चित रूप से इष्टतम विकल्प है। अगर मैं अस्पष्ट था, तो मेरी माफ़ी।
तोमर

4

इस प्रश्न का उत्तर वस्तुओं की संख्या और उनके आकार और आपके बजट पर निर्भर करता है। इस पर निर्भर करता है कि हमारे पास 3 मामले हैं:

1- तालिका में वस्तुओं की संख्या और आकार की संख्या बहुत अधिक नहीं है। तब जैसा कि स्टीफन ओपल ने कहा कि आप उपयोगकर्ता के लिए सभी वस्तुओं को पुनः प्राप्त करने के लिए स्कैन के बजाय क्वेरी का उपयोग कर सकते हैं और फिर सभी लौटी वस्तुओं पर लूप कर सकते हैं और या तो सुविधा DeleteItemयाBatchWriteItem। लेकिन ध्यान रखें कि आप यहां बहुत सारी थ्रूपुट क्षमता को जला सकते हैं। उदाहरण के लिए, ऐसी स्थिति पर विचार करें, जहां आपको डायनमोबीडी तालिका से 1000 आइटम हटाने की आवश्यकता होती है। मान लें कि प्रत्येक आइटम आकार में 1 KB है, जिसके परिणामस्वरूप लगभग 1MB डेटा है। बल्क-डिलीट करने के इस कार्य के लिए क्वेरी और डिलीट के लिए कुल 2000 लिखने की क्षमता वाली इकाइयों की आवश्यकता होगी। 10 सेकंड के भीतर इस डेटा लोड को निष्पादित करने के लिए (जिसे कुछ अनुप्रयोगों में भी तेज नहीं माना जाता है), आपको तालिका के 200 लिखने की क्षमता इकाइयों में प्रावधानित राइट थ्रूपुट को सेट करना होगा। जैसा कि आप इसका उपयोग करने के लिए इस तरह से उपयोग करने के लिए देख सकते हैं यदि इसकी कम संख्या में आइटम या छोटे आकार के आइटम हैं।

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

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


0

मेरा दृष्टिकोण एक तालिका से सभी पंक्तियों को हटाने के लिए है, डायनमोर्डब सिर्फ डायनमोब्स स्कैनएर्सक्यूइन का उपयोग करके तालिका से सभी पंक्तियों को बाहर निकालने के लिए है, और फिर परिणाम सूची को डायनामोड्स एडडेलीटम्स को खिलाएं। नीचे C # में कोड मेरे लिए ठीक काम करता है।

        public async Task DeleteAllReadModelEntitiesInTable()
    {
        List<ReadModelEntity> readModels;

        var conditions = new List<ScanCondition>();
        readModels = await _context.ScanAsync<ReadModelEntity>(conditions).GetRemainingAsync();

        var batchWork = _context.CreateBatchWrite<ReadModelEntity>();
        batchWork.AddDeleteItems(readModels);
        await batchWork.ExecuteAsync();
    }

नोट: तालिका को हटाने और फिर वेब कंसोल से इसे फिर से बनाने के लिए तालिका बनाने के लिए YAML / CloudFront का उपयोग करने पर समस्या हो सकती है।


0

हमारे पास डायनेमो टेबल को छोटा करने का विकल्प नहीं है। हमें तालिका को छोड़ना होगा और फिर से बनाना होगा। डायनॉम्बो चार्ज रीडचैप्नेस यूनीटस और राइटकैपसिटी यूनीट पर आधारित हैं। अगर हम BatchWriteItem फ़ंक्शन का उपयोग करके सभी आइटम हटाते हैं, तो यह WriteCapacityUnits.So का उपयोग करेगा ताकि विशिष्ट रिकॉर्ड्स को हटाया जा सके या तालिका को हटाकर फिर से शुरू किया जा सके।

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