Qcache_free_memory पूर्ण नहीं है फिर भी मुझे Qcache_lowmem_prunes का एक बहुत कुछ मिलता है


11

मैंने अभी-अभी हमारे CMS के लिए क्वेरी कैश के साथ डबिंग शुरू की है।

किसी को भी मुझे (या कम से कम एक अच्छा अनुमान दे) बता सकते हैं क्यों मैं एक बहुत की Qcache_lowmem_prunesजब आधे से अधिक Qcache_free_memoryनि: शुल्क है?

query_cache_size=512M
query_cache_limit=1M

लगभग 12 घंटे के बाद ऐसा दिखता है

show status like '%qcach%';
+-------------------------+-----------+
| Variable_name           | Value     |
+-------------------------+-----------+
| Qcache_free_blocks      | 10338     | 
| Qcache_free_memory      | 297348320 | 
| Qcache_hits             | 10254104  | 
| Qcache_inserts          | 6072945   | 
| Qcache_lowmem_prunes    | 725279    | 
| Qcache_not_cached       | 2237603   | 
| Qcache_queries_in_cache | 48119     | 
| Qcache_total_blocks     | 111346    | 
+-------------------------+-----------+

इस प्रकार इसकी देखभाल की गई flush query cache;

show status like '%qcach%';
+-------------------------+-----------+
| Variable_name           | Value     |
+-------------------------+-----------+
| Qcache_free_blocks      | 1         | 
| Qcache_free_memory      | 443559256 | 
| Qcache_hits             | 10307015  | 
| Qcache_inserts          | 6115890   | 
| Qcache_lowmem_prunes    | 725279    | 
| Qcache_not_cached       | 2249405   | 
| Qcache_queries_in_cache | 26455     | 
| Qcache_total_blocks     | 54490     | 
+-------------------------+-----------+

जवाबों:


21

क्वेरी कैश एक बहुत अच्छी सुविधा है, लेकिन इस पर बहुत अधिक ध्यान देने की परीक्षा न करें और इसे बहुत बड़ा बनाने के लिए लुभाएं नहीं। इसके कुछ इंटर्नल को समझने से शायद उस संबंध में मदद मिलेगी।

क्वेरी कैश उपलब्ध मेमोरी के एक बड़े सन्निहित भाग के रूप में शुरू होता है। फिर "ब्लॉक" को इस बड़े ब्लॉक से उकेरा गया:

  • प्रत्येक कैश्ड क्वेरी एक ब्लॉक लेती है
  • इसके साथी परिणाम एक ब्लॉक लेता है
  • किसी भी कैश्ड क्वेरी द्वारा संदर्भित प्रत्येक तालिका (उस तालिका में कैश में कितनी भी क्वेरीज़ का संदर्भ देने वाली कोई भी बात नहीं है) एक ब्लॉक, एक टेबल प्रति भी लेती है।

ब्लॉक का आकार गतिशील है, लेकिन सर्वर query_cache_min_res_unit4096 बाइट्स के एक सामान्य डिफ़ॉल्ट के साथ, प्रति ब्लॉक न्यूनतम बाइट्स आवंटित करता है ।

किसी भी समय प्रश्न, उनके साथ परिणाम, और तालिका संदर्भ कैश से हटा दिए जाते हैं, या तो अंतर्निहित तालिकाओं द्वारा अमान्य हो जाते हैं या नए प्रश्नों के लिए जगह बनाने के लिए छंटाई करके, यह नए छेदों को छोड़ देता है, हालांकि उन ब्लॉकों का आकार बड़ा था, और "मुक्त ब्लॉक" की संख्या आमतौर पर बढ़ जाती है ... हालांकि यदि दो या अधिक सन्निहित ब्लॉक मुक्त हो जाते हैं, तो "मुक्त ब्लॉक" की संख्या केवल 1 से बढ़ जाती है, और "मुक्त ब्लॉक" बिल्कुल नहीं बढ़ेंगे यदि नव- मुक्त ब्लॉक पहले से ही मुक्त ब्लॉक के साथ सन्निहित हैं - उस मुक्त ब्लॉक का आकार बस बड़ा हो जाता है। क्वेरी कैश में मुक्त मेमोरी के किसी भी खुले ब्लॉक को 1 निःशुल्क ब्लॉक के रूप में गिना जाता है।

बेशक, एक नि: शुल्क ब्लॉक से कम का query_cache_min_res_unitउपयोग नहीं किया जाएगा।

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

यह पूछना समझदारी होगी कि सर्वर मेमोरी को डिफ्रैग्मेंट क्यों नहीं करता ... लेकिन इससे कोई मतलब नहीं होगा। जब यह हो सकता है तो क्वेरी कैश मदद करता है लेकिन यह बिल्कुल भी रणनीतिक नहीं है। आप अनावश्यक रखरखाव कार्यों के साथ प्रसंस्करण समय (विशेषकर वैश्विक लॉक में बिताए समय) का निवेश नहीं करना चाहते हैं।

यह सर्वर के लिए काउंटर-रीफ़्रैगिंग - डिफ्रैगमेंटिंग - क्वेरी कैश में मेमोरी खर्च करने के लिए काउंटर-उत्पादक होगा, क्योंकि कैश किए गए परिणाम लगातार बदल रहे हैं और कैश का पूरा बिंदु प्रदर्शन में सुधार करना है।

वैश्विक लॉक एक बहुत अच्छा कारण है कि आप अत्यधिक बड़े क्वेरी कैश का उपयोग नहीं करना चाहते हैं ... सर्वर वहां बहुत अधिक समय बिताएगा क्योंकि प्रश्न यह देखने के लिए अपनी बारी का इंतजार करते हैं कि क्या वे कैश होने के लिए होते हैं और आपके प्रदर्शन को नुकसान होगा। ।

लेकिन qcache_free_blocksअनिवार्य रूप से मुक्त-अंतरिक्ष विखंडन का सूचक है। क्वेरी कैश में अब उपलब्ध मेमोरी के कई अनियंत्रित ब्लॉक मौजूद हैं। कैश में डाली जाने वाली नई क्वेरी के लिए, क्वेरी, इसके परिणाम और (कभी-कभी) इसकी तालिका संदर्भों को शामिल करने के लिए खाली स्थान का एक बड़ा हिस्सा होना चाहिए। अगर वहाँ नहीं है, तो कुछ और जाना है ... जो आप देख रहे हैं। ध्यान दें, फिर से, कि उपलब्ध स्थान हमेशा जरूरी नहीं है कि वह सन्निहित हो (जो मैं स्रोत कोड पढ़कर बता सकता हूं), लेकिन विखंडन होने पर हर छेद नहीं भरा जाएगा।

लेकिन विखंडन एक दिए गए कार्यभार के लिए समय के साथ बाहर ले जाने के लिए जाता है, क्योंकि आमतौर पर जब तक आप उम्मीद कर सकते हैं तब तक क्वेरी कैश में कुछ भी नहीं रहता है।

इसका कारण यह है, कुछ मायनों में, क्वेरी कैश अपनी सादगी में शानदार है।

किसी भी समय कैश्ड क्वेरी परिवर्तनों द्वारा संदर्भित तालिका में डेटा, उस तालिका में शामिल सभी क्वेरीज़ कैश से निकाल दी जाती हैं - भले ही परिवर्तन कैश्ड परिणामों को प्रभावित न करता हो। यह तब भी सच है जब एक तालिका बदलती है, लेकिन नहीं बदलती है, जैसा कि एक InnoDB लेनदेन के मामले में है जो वापस लुढ़का हुआ है। उस तालिका को संदर्भित करने वाली क्वेरी कैश प्रविष्टियाँ पहले से ही शुद्ध थीं।

साथ ही, क्वेरी कैश को प्रत्येक आने वाली क्वेरी के लिए जाँच की जाती है इससे पहले कि सर्वर वास्तव में क्वेरी को पार्स करता है। केवल एक चीज जो मेल खाएगी वह एक और क्वेरी है जो ठीक उसी तरह थी, बाइट-फॉर-बाइट। SELECT * FROM my_tableऔर select * from my_tableबाइट के लिए बाइट समान नहीं हैं, इसलिए क्वेरी कैश को यह पता नहीं है कि वे एक ही क्वेरी हैं।

FLUSH QUERY CACHEक्वेरी कैश खाली नहीं करता है। यह क्वेरी कैश को डीफ़्रैग्मेन्ट करता है, यही वजह है कि Qcache_free_blocks"1." सभी रिक्त स्थान को समेकित किया गया है।

RESET QUERY CACHE वास्तव में क्वेरी कैश के सभी सामग्री को निकालता है (निकालता है)।

FLUSH STATUSकाउंटरों को साफ करता है, लेकिन यह कुछ ऐसा नहीं है जिसे आप नियमित रूप से करना चाहते हैं क्योंकि यह स्थिति के अधिकांश वेरिएबल्स को शून्य कर देता है SHOW STATUS

यहाँ कुछ त्वरित प्रदर्शन हैं।

आधारभूत:

mysql> show status like '%qcache%';
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 1        |
| Qcache_free_memory      | 67091120 |
| Qcache_hits             | 0        |
| Qcache_inserts          | 0        |
| Qcache_lowmem_prunes    | 0        |
| Qcache_not_cached       | 1        |
| Qcache_queries_in_cache | 0        |
| Qcache_total_blocks     | 1        |
+-------------------------+----------+

एक क्वेरी चलाएँ ...

mysql> select * from junk where id = 2;

कुल ब्लॉकों में 3 की वृद्धि हुई है, 1 से आवेषण और कैश में क्वेरी 1 है।

+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 1        |
| Qcache_free_memory      | 67089584 |
| Qcache_inserts          | 1        |
| Qcache_queries_in_cache | 1        |
| Qcache_total_blocks     | 4        |
+-------------------------+----------+

एक ही क्वेरी चलाएँ, लेकिन विभिन्न पूंजीकरण के साथ ...

mysql> SELECT * FROM junk where id = 2;

इस क्वेरी को अलग से कैश किया गया था। कुल ब्लॉक केवल 2 से बढ़ गए क्योंकि हमारे पास पहले से ही टेबल के लिए आवंटित ब्लॉक था।

+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 1        |
| Qcache_free_memory      | 67088560 |
| Qcache_inserts          | 2        |
| Qcache_queries_in_cache | 2        |
| Qcache_total_blocks     | 6        |
+-------------------------+----------+

अब, हम तालिका में एक अलग पंक्ति बदलते हैं ।

mysql> update junk set things = 'items' where id = 1;

दोनों प्रश्न और तालिका संदर्भ कैश से अमान्य हैं, हमें 1 सन्निहित मुक्त ब्लॉक के साथ छोड़ रहे हैं, सभी कैश मेमोरी से मुक्त हो गए हैं, और सभी मुक्त स्थान एक ब्लॉक में समेकित हैं।

+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 1        |
| Qcache_free_memory      | 67091120 |
| Qcache_queries_in_cache | 0        |
| Qcache_total_blocks     | 1        |
+-------------------------+----------+

MySQL कैश में एक क्वेरी स्टोर नहीं करेगा जो नियतात्मक नहीं है - जैसे कि SELECT NOW();या कोई भी क्वेरी जो आप इसे विशेष रूप से कैश करने के लिए नहीं बताते हैं। SELECT SQL_NO_CACHE ...सर्वर को कैश में परिणामों को संग्रहीत नहीं करने के लिए कहने का निर्देश है। यह एक क्वेरी के वास्तविक निष्पादन समय को बेंचमार्किंग के लिए उपयोगी है जब कैश आपको बाद के निष्पादन पर एक भ्रामक तेजी से प्रतिक्रिया दे रहा है।


आपके उदाहरणों में, क्या यह सही है कि query_cache_min_res_unit = 512? मुक्त स्मृति 1 और 4 उपयोग किए गए ब्लॉकों के बीच 512 * 3 से नीचे चली जाती है और 4 और 6 उपयोग किए गए ब्लॉकों के बीच 512 * 2 होती है।
अलंड

1
@aland जो एक बहुत अच्छी बात है। नहीं, मुझे 4096 के डिफ़ॉल्ट मूल्य का उपयोग करना चाहिए था। ऐसा लगता है जैसे क्वेरी कैश इसे भरने के बाद दो की सबसे छोटी संभव शक्ति को ब्लॉक करता है, अंत में खाली स्थान छोड़ता है, ताकि 7/8 वीं मूल रूप से आवंटित पूरे 4096 बाइट फंसे नहीं हैं। मुझे इसमें और गहराई से खुदाई करनी होगी।
माइकल - sqlbot
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.