InnoDB इंजन के साथ इन्सर्ट में देरी का उपयोग कैसे करें और इन्सर्ट स्टेटमेंट के लिए कम कनेक्शन का उपयोग करें?


10

मैं एक ऐसे एप्लिकेशन पर काम कर रहा हूं जिसमें बहुत सारे डेटाबेस शामिल हैं, लगभग ~ 70% आवेषण और 30% रीड। इस अनुपात में वे अपडेट भी शामिल होंगे जिन्हें मैं एक पढ़ने और एक लिखने के लिए मानता हूं। डालने के बयानों के माध्यम से कई ग्राहक डेटाबेस में डेटा सम्मिलित करते हैं, नीचे दिए गए विवरण के माध्यम से:

$mysqli->prepare("INSERT INTO `track` (user, uniq_name, ad_name, ad_delay_time ) values (?, ?, ?, ?)");

सवाल मैं या तो उपयोग करना चाहिए है insert_delay या उपयोग mysqli_multi_query क्योंकि डालने बयान सर्वर पर ~ 100% CPU का इस्तेमाल तंत्र। मैं अपने डेटाबेस पर InnoDB इंजन का उपयोग कर रहा हूं इसलिए विलंबित सम्मिलित करना संभव नहीं है। सर्वर पर प्रविष्टि ~ 36k / hr और 99.89% पढ़ी जाती है, मैं भी चुनिंदा कथन का उपयोग कर रहा हूं जिसमें एकल क्वेरी में डेटा को सात बार प्राप्त होता है , इस क्वेरी को निष्पादित करने के लिए सर्वर पर 150 सेकंड लगते हैं। इस कार्य के लिए मैं किस तरह की तकनीक या तंत्र का उपयोग कर सकता हूं? मेरी सर्वर मेमोरी 2 जीबी है, क्या मुझे मेमोरी का विस्तार करना चाहिए? इस समस्या पर एक नजर है, किसी भी सुझाव मुझे आभारी होंगे।

तालिका की संरचना:

+-----------------+--------------+------+-----+-------------------+----------------+
| Field           | Type         | Null | Key | Default           | Extra          |
+-----------------+--------------+------+-----+-------------------+----------------+
| id              | int(11)      | NO   | PRI | NULL              | auto_increment |
| user            | varchar(100) | NO   |     | NULL              |                |
| uniq_name       | varchar(200) | NO   |     | NULL              |                |
| ad_name         | varchar(200) | NO   |     | NULL              |                |
| ad_delay_time   | int(11)      | NO   |     | NULL              |                |
| track_time      | timestamp    | NO   | MUL | CURRENT_TIMESTAMP |                |
+-----------------+--------------+------+-----+-------------------+----------------+

मेरा डेटाबेस वर्तमान स्थिति, यह 41k सम्मिलन (लिखता है) दिखाता है, जो मेरे डेटाबेस के लिए बहुत धीमा है।

डेटाबेस की स्थिति


क्या आप तालिका की परिभाषा की आपूर्ति कर सकते हैं? (सभी कॉलम, डेटाटाइप और इंडेक्स)
ypercube

क्या आप अपना संक्षिप्त स्निपेट दे सकते हैं SHOW FULL PROCESSLISTजब यह 100% सीपीयू ले रहा हो? आप कितने कनेक्शन की अनुमति दे रहे हैं इस दौरान कितने ले लिए जाते हैं?
डेरेक डाउनी

कृपया इन दो प्रश्नों को चलाएं: SHOW GLOBAL VARIABLES LIKE 'innodb%';और SELECT VERSION();अपना आउटपुट प्रदर्शित करें।
रोलैंडमाइसीडीडीबीए

कृपया प्रति सेकंड आवेषण की संख्या प्रदान करें जिसे आप निष्पादित कर रहे हैं।
dabest1

आपका कोड SQL इंजेक्शन के लिए अतिसंवेदनशील है। तैयार किए गए कथनों और मानकीकृत मूल्यों का उपयोग करें।
एरॉन ब्राउन

जवाबों:


12

चूँकि आपके पास और अधिक लेख हैं, तो पढ़ता है, मैं निम्नलिखित अनुशंसा करना चाहूंगा

इनोबीडी की निर्णय ट्यूनिंग कुंजी होगी

बफ़र पूल ( साइज़ द्वारा innodb_buffer_pool_size )

चूंकि InnoDB INSERT DELAYED का समर्थन नहीं करता है , एक बड़े InnoDB बफर पूल का उपयोग करना निकटतम चीज़ है जो आप INSERT DELAYED को प्राप्त कर सकते हैं। सभी DML (INSERTs, UPDATEs और DELETEs) को InnoDB बफ़र पूल में कैश किया जाएगा। राइट्स के लिए लेन-देन की जानकारी तुरंत Redo Logs (ib_logfile0, ib_logfile1) को लिखी जाती है। बफ़र पूल में पोस्ट किए गए लेखन को समय-समय पर मेमोरी से डिस्क में ibdata1 (सेकेंडरी बफ़र के लिए सेकेंडरी इंडेक्स, डबल राइट बफर) के माध्यम से फ्लश किया जाता है। बड़ा पूल, INSERTs की बड़ी राशि को कैश किया जा सकता है। 8GB या अधिक RAM वाले सिस्टम में, 75-80% RAM का उपयोग innodb_buffer_pool_size के रूप में करें। बहुत कम रैम वाले सिस्टम में, 25% (ओएस को समायोजित करने के लिए)।

CAVEAT: आप innodb_doublewrite को 0 पर सेट करने के लिए और भी अधिक गति लिख सकते हैं, लेकिन डेटा अखंडता के जोखिम पर। OS में कैशिंग InnoDB को रोकने के लिए O_DIRECT पर innodb_flush_method सेट करने के साथ आप चीजों को गति भी दे सकते हैं ।

Redo Logs ( innodb_log_file_size द्वारा आकार दिया गया )

डिफ़ॉल्ट रूप से, Redo लॉग का नाम ib_logfile0 और ib_logfile1 होता है और प्रत्येक 5MB होगा। आकार 25% innodb_buffer_pool_size होना चाहिए। यदि पहले से मौजूद लॉग लॉग मौजूद हैं, my.cnf में नई सेटिंग जोड़ें, mysql को बंद करें, उन्हें हटाएं और mysql को पुनरारंभ करें

लॉग बफ़र ( innodb_log_buffer_size द्वारा आकार दिया गया )

लॉग बफ़र को लाल लॉग में फ्लश करने से पहले रैम में बदलाव करता है। डिफ़ॉल्ट 8M है। लॉग बफर जितना बड़ा होगा, डिस्क I / O उतना ही कम होगा। बहुत बड़े लेन-देन से सावधान रहें, क्योंकि यह मिलिस द्वारा कमियों को धीमा कर सकता है।

कई सीपीयू तक पहुँच

MySQL 5.5 और MySQL 5.1 InnoDB Plugin में InnoDB Storage Engine का उपयोग करने के लिए कई CPU हैं। यहां वे विकल्प हैं जिन्हें आपको सेट करने की आवश्यकता है:

  • innodb_thread_concurrency ऊपरी समवर्ती धागों की संख्या पर ऊपरी सीमा निर्धारित करता है जिसे InnoDB खुला रख सकता है। यह आमतौर पर इसके लिए निर्धारित करने की सिफारिश की जाती है (सीपीयू के 2 एक्स नंबर) + डिस्क की संख्या। पिछले साल, मैंने पेरकोना एनवाईसी कॉन्फ्रेंस से पहली बार सीखा कि आप इसे इनओडीडी स्टोरेज इंजन को सचेत करने के लिए इसे सेट करें ताकि जिस पर्यावरण में यह चल रहा है, उसके लिए सबसे अच्छी संख्या में धागे मिल सकें।
  • innodb_concurrency_ticket ऐसे थ्रेड्स की संख्या सेट करता है जो इंप्यूनिटी के साथ कंसीडर चेकिंग को बायपास कर सकते हैं। उस सीमा तक पहुँच जाने के बाद, थ्रेड कंसिस्टेंसी जाँच फिर से आदर्श बन जाती है।
  • innodb_commit_concurrency समवर्ती लेनदेन की संख्या निर्धारित करता है जिसे प्रतिबद्ध किया जा सकता है। चूंकि डिफॉल्ट 0 है, इसलिए इसे सेट न करना किसी भी तरह के लेनदेन को एक साथ करने की अनुमति देता है।
  • innodb_thread_sleep_delay , एक InnoDB धागे की संख्या को निर्धारित करता है जो InnoDB कतार को पुन: दर्ज करने से पहले निष्क्रिय हो सकता है। डिफ़ॉल्ट 10000 (10 सेकंड) है।
  • innodb_read_io_threads (इसे 3000 पर सेट करें) और innodb_write_io_threads (इसे 7000 पर सेट करें) (दोनों MySQL 5.1.38 के बाद से) रीड और राइट के लिए निर्दिष्ट थ्रेड की संख्या आवंटित करते हैं। डिफ़ॉल्ट 4 है और अधिकतम 64 है। इन्हें 64 पर सेट करें। इसके अलावा, innodb_io_capacity को 10000 पर सेट करें ।

MySQL 5.5 में अपग्रेड करें

यदि आपके पास MySQL 5.0 है, तो MySQL 5.5 में अपग्रेड करें। यदि आपके पास MySQL 5.1.37 या पूर्व है, तो MySQL 5.5 में अपग्रेड करें। यदि आपके पास MySQL 5.1.38 या इसके बाद का संस्करण है और MySQL 5.1 में बने रहना चाहते हैं, तो InnoDB प्लगइन स्थापित करें। इस तरह, आप InnoDB के लिए सभी CPU का लाभ उठा सकते हैं।


मेरी सर्वर मेमोरी 2GB है, इसलिए मैमोरी के अनुसार मैंने innodb बफर पूल को 500M में सेट किया है, और फाइलों को 25% पूल में लॉग किया है, लॉग बफर को 64M पर भी सेट किया है। लेकिन फिर भी सर्वर भारी व्यस्त है। क्या मुझे मेमोरी को अपग्रेड करना चाहिए? इसके अलावा मेरा सर्वर 32 बिट ubuntu पर है, इसलिए अधिकतम मैं 4 जीबी तक मेमोरी सेट कर सकता हूं।
शशांक

यदि सर्वर सिर्फ MySQL (कोई अपाचे, कोई PHP) के लिए नहीं है, तो innodb_buffer_pool_size 75% 2GB हो सकता है, जो कि 1536M है। यदि आप 4GB में अपग्रेड करते हैं, तो innodb_buffer_pool_size 3G हो सकता है। लॉग फाइलें बफर पूल का 25% होना चाहिए जैसा आपने कहा था।
RolandoMySQLDBA

सर्वर Apache2, mysql और php पर चल रहा है, क्या मुझे इस स्थिति में मेमोरी को अपग्रेड करने के लिए जाना चाहिए या क्या इनसाइड बफर बफर को छोड़कर कोई इष्टतम समाधान है?
शशांक

यह व्यक्ति आपसे असहमत है: percona.com/blog/2008/11/21/… Percona के साथ बहस करने के लिए मुश्किल।
ज़ेनेक्सर

रोलांडो - सुझाव है कि आप 5.6 और 5.7 के अपडेट के साथ उत्तर जोड़ें। चूक बदल गई है; अन्य सेटिंग्स उपलब्ध हैं; आदि में शायद पेरकोना और मारियाडीबी और 8.0 युक्तियां शामिल हैं।
रिक जेम्स

2

INT (2) अभी भी 4 बाइट्स का उपयोग करता है - शायद आपका मतलब था टिनिटेड अनसोल्ड?

सेटनो में कितने भिन्न मूल्य हैं? यदि यह छोटा है, तो कुंजी (सेटनो) का उपयोग कभी नहीं किया जाएगा। INSERTing को उस इंडेक्स को अपडेट करना होगा; कुंजी को हटाने से कुछ निष्क्रिय हो जाएंगे।

CHAR (10) - क्या flagहमेशा 10 अक्षर लंबे होते हैं? और utf8 में? शायद आप ध्वज VARCHAR (10) चार्जर सेट का उपयोग कर सकते हैं

अपने आवेषण बैच - एक बार में 100 तेजी से 10 बार चलेंगे। (100 के पार 'कम रिटर्न' में मिल रहा है।)

ऑटोकॉमिट का मूल्य क्या है? क्या आप प्रत्येक INSERT को BEGIN ... COMMIT में लपेट रहे हैं? Innodb_flush_log_at_trx_commit का मान क्या है?


अगर मैं डेटा को बाह्य स्रोत के माध्यम से अलग-अलग ग्राहकों जैसे विभिन्न मूल्यों के साथ सम्मिलित करता हूं, तो मैं कैसे सम्मिलित हो सकता हूं .... क्या यह विश्वसनीय है अगर मैंने उपयोग किया है: codet_name (col1, col2, col3) मानों में डालें (val1, val2, val3), (val1, val2, val3), (val1, val2, val3), (val1, val2, val3), (val1, val2, val3); code
शशांक

1

एक कतार लगाओ। अनुप्रयोग एक समय में एक पंक्ति 1 पंक्ति में लिखता है और फिर पंक्तियों को बाहर निकालता है और बैच में एक डेटाबेस में सम्मिलित करता है जो पिछली प्रविष्टि के बाद से पारित समय की मात्रा की पंक्तियों की संख्या के आधार पर होता है।

मैंने देखा है कि आवेषणों को एक बार में 10,000 बैचना सबसे तेज़ है, इसलिए आपको एक मीठे स्थान को खोजने के लिए परीक्षण करना होगा।

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


मैं इस दृष्टिकोण से सहमत हूं- मैं एक ऐप पर हर 5 सेकंड में ~ 1500 आवेषण कर रहा हूं और यह दूसरा है। mysql लगता है कि कुछ तंत्र आंतरिक रूप से कार्यान्वित किया गया है जिससे बैच आवेषण वास्तव में बहुत जल्दी होता है।
डॉन वूल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.