Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

100 मिलियन पंक्तियों की प्रतिलिपि बनाने के लिए चुनिंदा क्वेरी में MySQL सम्मिलित करना बहुत धीमा है

कोई भी INSERT ... SELECT ... क्वेरी साझा लॉक प्राप्त करती है पंक्तियों पर यह चयन में स्रोत तालिका से पढ़ता है। लेकिन पंक्तियों के छोटे टुकड़ों को संसाधित करने से, लॉक बहुत लंबे समय तक नहीं टिकता है।

LIMIT ... OFFSET . के साथ क्वेरी जैसे-जैसे आप स्रोत तालिका के माध्यम से आगे बढ़ेंगे, यह धीमा और धीमा होता जाएगा। प्रति खंड 10,000 पंक्तियों पर, आपको उस क्वेरी को 10,000 बार चलाने की आवश्यकता है, प्रत्येक को नए ऑफ़सेट तक पहुँचने के लिए फिर से शुरू करना होगा और तालिका के माध्यम से स्कैन करना होगा।

कोई फर्क नहीं पड़ता कि आप क्या करते हैं, 100 मिलियन पंक्तियों की प्रतिलिपि बनाने में कुछ समय लगेगा। यह बहुत काम कर रहा है।

मैं pt-archiver का उपयोग करूंगा , इस उद्देश्य के लिए डिज़ाइन किया गया एक निःशुल्क टूल। यह पंक्तियों को "हिस्सा" (या सबसेट) में संसाधित करता है। यह विखंडू के आकार को गतिशील रूप से समायोजित करेगा ताकि प्रत्येक खंड में 0.5 सेकंड का समय लगे।

आपकी विधि और पीटी-संग्रहकर्ता के बीच सबसे बड़ा अंतर यह है कि पीटी-संग्रहकर्ता LIMIT ... OFFSET का उपयोग नहीं करता है , यह प्राथमिक कुंजी सूचकांक के साथ चलता है, स्थिति के बजाय मूल्य के आधार पर पंक्ति के भाग का चयन करता है। इसलिए हर खंड को अधिक कुशलता से पढ़ा जाता है।

अपनी टिप्पणी दें:

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

इसका कारण यह है कि जब आप LIMIT . का उपयोग करते हैं OFFSET . के साथ , प्रत्येक क्वेरी को तालिका के प्रारंभ में शुरू करना होता है, और पंक्तियों को OFFSET तक गिनना होता है मूल्य। जैसे-जैसे आप तालिका के माध्यम से पुनरावृति करते हैं यह लंबा और लंबा होता जाता है।

OFFSET . का उपयोग करके 20,000 महंगी क्वेरी चलाना 10,000 समान प्रश्नों को चलाने में अधिक समय लगेगा। सबसे महंगा हिस्सा 5,000 या 10,000 पंक्तियों को पढ़ना या उन्हें गंतव्य तालिका में सम्मिलित करना नहीं होगा। महंगा हिस्सा ~50,000,000 पंक्तियों को बार-बार छोड़ता रहेगा।

इसके बजाय, आपको टेबल पर मानों . द्वारा पुनरावृति करनी चाहिए ऑफ़सेट द्वारा नहीं।

INSERT IGNORE INTO Table2(id, field2, field3)
        SELECT f1, f2, f3
        FROM Table1
        WHERE id BETWEEN rowOffset AND rowOffset+limitSize;

लूप से पहले, MIN(id) और MAX(id) को क्वेरी करें, और rowOffset शुरू करें न्यूनतम मान पर, और अधिकतम मान तक लूप करें।

पीटी-संग्रहकर्ता इस तरह काम करता है।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. स्प्रिंग डेटा जेपीए utf-8 एन्कोडिंग काम नहीं कर रहा है

  2. कॉलम नाम में आरक्षित शब्द - MySQL में डालें

  3. mysql में साउंडएक्स () को कैसे क्वेरी करें?

  4. mysql.user की कॉलम संख्या गलत है। अपेक्षित 42, 44 मिला। तालिका शायद दूषित है

  5. सम्मिलित करते समय अन्य कॉलम के आधार पर परिकलित फ़ील्ड मान