2010-10-17 15 views
9

मेरे पास एक ऐसा ऐप है जिसे बड़ी संख्या में प्रविष्टियों पर बड़ी मात्रा में डेटा अपडेट करने की आवश्यकता है। असल में यह कुछ 7,000 आवेषण और/या अपडेट करता है लेकिन इसमें बहुत समय लगता है (लगभग 9 मिनट ... प्रति क्वेरी 0.08 सेकेंड औसत)। अनिवार्य रूप से मैं ऐसे कई अनुरोध करने के लिए सामान्य गति अप की तलाश में हूं (मुझे अपने अस्पष्ट उदाहरण के लिए एक विशिष्ट उत्तर की उम्मीद नहीं है ... उम्मीद है कि, उम्मीद है कि, समझाने में मदद करें)।बड़ी संख्या में mysql अद्यतनों और आवेषणों को तेज करना

SELECT `habitable_planets`.* FROM `habitable_planets` WHERE (timestamp = '2010-10-15T07:30:00-07:00') AND (planet_id = '2010_Gl_581_c') 

INSERT INTO `habitable_planets` (`planet_id`, `timestamp`, `weather_air_temp`, `weather_cell_temp`, `weather_irradiance`, `weather_wind_float`, `biolumin_to_date`, `biolumin_detected`, `craft_energy_usage`, `craft_energy_consumed_to_date`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 

SELECT `habitable_planets`.* FROM `habitable_planets` WHERE (timestamp = '2010-10-15T07:45:00-07:00') AND (planet_id = '2010_Gl_581_c') 

INSERT INTO `habitable_planets` (`planet_id`, `timestamp`, `weather_air_temp`, `weather_cell_temp`, `weather_irradiance`, `weather_wind_float`, `biolumin_to_date`, `biolumin_detected`, `craft_energy_usage`, `craft_energy_consumed_to_date`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 

दोहराएँ बारंबार (अच्छी तरह से, लगभग 7,000 बार):

यहाँ अनुरोधों की रूपरेखा से कुछ नमूने हैं। यह एक अद्यतन है जो 24 घंटे की अवधि में अंतराल पर उत्पन्न डेटा एकत्र करता है और फिर प्रति दिन एक बार डेटाबेस में भारी अद्यतन करता है। सीमित बिट को देखते हुए मैंने दिखाया है कि आप इस प्रक्रिया को तेज करने के लिए कोई सुझाव हैं?

उदाहरण के लिए ... क्या प्रत्येक टाइमस्टैम्प के लिए चयन करने के बजाए यह समझ में आता है, क्या एक बार एक श्रेणी के लिए चयन करें और फिर स्क्रिप्ट में उन पर फिर से प्रयास करें?

थोड़ा की तरह:

SELECT `habitable_planets`.* FROM `habitable_planets` WHERE (planet_id = '2010_Gl_581_c') 

असाइन कि $foo के परिणाम और उसके बाद कार्य करें:

foreach ($foo as $bar) 
{ 
    if ($bar['timestamp'] == $baz) // where $baz is the needed timestamp 
    { 
    // do the insert here 
    } 
} 

संपादित करें: यह करने के लिए एक सा जोड़ने के लिए, एक बात है कि मेरी स्थिति में जवाबदेही में सुधार हुआ था मौजूदा रिकॉर्ड के लिए चेक किए गए कोड का एक गुच्छा बदलने के लिए और INSERT... ON DUPLICATE KEY UPDATE एसक्यूएल क्वेरी का उपयोग करने के परिणामस्वरूप या तो एक डालने या अपडेट किया गया। इसके परिणामस्वरूप मेरे विशेष मामले में लगभग 30% की गति वृद्धि हुई क्योंकि यह समीकरण के बाहर डेटाबेस में कम से कम एक यात्रा काटता है और हजारों अनुरोधों से यह वास्तव में जुड़ जाता है।

उत्तर

16

कुछ उपयोगी लिंक्स:

MySQL प्रलेखन से:

Speed of INSERT Statements का कहना है:

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

  • यदि एकाधिक ग्राहक बहुत सारी पंक्तियां डाल रहे हैं, तो आप INSERT DELAYED कथन का उपयोग कर उच्च गति प्राप्त कर सकते हैं।

  • एक MyISAM तालिका के लिए, आप एक ही समय कि बयानों का चयन करें, चल रहे हैं पर पंक्तियां जोड़ने के लिए समवर्ती आवेषण उपयोग कर सकते हैं अगर कोई हटाए गए पंक्तियों डेटा फ़ाइल के बीच में हैं।

  • टेक्स्ट फ़ाइल से कोई तालिका लोड करते समय, लोड डेटा इन्फाइल का उपयोग करें। यह INSERT कथन का उपयोग करने से आमतौर पर 20 गुना तेज है।

  • कुछ अतिरिक्त कार्य के

    , जब तालिका कई अनुक्रमित है डेटा लोड INFILE चलाने एक MyISAM तालिका के लिए तेजी से भी बनाने के लिए संभव है।

+1

+1। अच्छा कॉम्पेन्सिव जवाब। – sberry

2

आप पहले से ही नहीं कर रहे हैं, (या तो mysqli, PDO, या कुछ अन्य डीबी पुस्तकालय है कि उन्हें समर्थन करता है, के माध्यम से) तैयार बयान का उपयोग करें। एक ही तैयार कथन का पुन: उपयोग करना और पैरामीटर मानों को बदलने से गति की चीजों में मदद मिलेगी, क्योंकि MySQL सर्वर को केवल एक बार क्वेरी को पार्स करना होगा।

INSERT एस VALUES के कई सेट प्रदान करके बैच किया जा सकता है - एक पंक्ति जो कई पंक्तियों को सम्मिलित करती है, एक पंक्ति को सम्मिलित करने वाले व्यक्तिगत प्रश्नों की समतुल्य संख्या से बहुत तेज है।

2

जो आप सुझाव देते हैं वह सही है। सर्वर पर भेजे गए प्रश्नों की मात्रा को कम करने का प्रयास करें क्योंकि यह आपको एकाधिक संचार ओवरहेड से बचाएगा।

बेशक, यदि आंतरिक चयन श्रेणी क्वेरी बहुत अधिक डेटा लौटाती है, तो आपके पास PHP पर एक बाधा हो सकती है।

1

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

(मैं सिर्फ पढ़ा है कि ब्रह्माण्ड में 10 लाख खरब रहने योग्य ग्रहों तो हो सकता है आप बेहतर bigint प्रयोग करेंगे अहस्ताक्षरित होने का अनुमान है: पी)

drop procedure if exists update_insert_habitable_planets; 

delimiter # 

create procedure update_insert_habitable_planets 
(
in p_planet_id int unsigned, 
in p_timestamp datetime, 
) 
proc_main:begin 

    start transaction; 

    -- bulk update/insert whatever 

    commit; 

end proc_main # 

delimiter ; 
+0

* "10 मिलियन ट्रिलियन" * - 10 क्विंटलियन :) – BadHorsie

संबंधित मुद्दे