खंडित MySQL तालिकाओं को कैसे खोजें और ठीक करें


27

मैंने MySQLTuner का उपयोग किया, जिसने बताया कि कुछ टेबल खंडित थे। मैंनें इस्तेमाल किया

mysqlcheck - अपनाएं -ए

सभी तालिकाओं का अनुकूलन करने के लिए। यह कुछ तालिकाओं को तय करता है लेकिन MySQLTuner अभी भी 19 तालिकाओं को खंडित पाता है। मैं यह कैसे देख सकता हूं कि डीफ़्रैग्मेंटिंग के लिए कौन से टेबल की जरूरत है? शायद इष्टतम समय काम करेगा जहां mysqlcheck नहीं किया गया? या मुझे और क्या प्रयास करना चाहिए?


1
मुझे एक ऐसी ही समस्या है। मैं MySQL 5.5 और कुछ InnoDB तालिकाओं के साथ एक नया DB स्थापित नहीं कर रहा हूँ जो कभी नहीं बेवजह। मुझे आश्चर्य हो रहा है कि यदि Data_free जाँच (कयाकजिम के उत्तर में दिखाया गया है) InnoDB तालिकाओं के साथ गलत है।
docwhat

जवाबों:


38

संक्षिप्त उत्तर:

select  ENGINE, TABLE_NAME,Round( DATA_LENGTH/1024/1024) as data_length , round(INDEX_LENGTH/1024/1024) as index_length, round(DATA_FREE/ 1024/1024) as data_free from information_schema.tables  where  DATA_FREE > 0;

"आपको पता होना चाहिए" उत्तर

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

यह प्रदर्शन को प्रभावित नहीं करता है, जब तक कि विखंडन बहुत बढ़ता है। बहुत अधिक विखंडन क्या है, अच्छी तरह से देखते हैं कि आप क्या देख रहे हैं:

  select  ENGINE, TABLE_NAME,Round( DATA_LENGTH/1024/1024) as data_length , round(INDEX_LENGTH/1024/1024) as index_length, round(DATA_FREE/ 1024/1024) as data_free from information_schema.tables  where  DATA_FREE > 0;

DATA_LENGTH और INDEX_LENGTH आपके डेटा और इंडेक्स का उपयोग करने वाले स्थान हैं, और DATA_FREE सभी तालिका पृष्ठों (विखंडन) में अप्रयुक्त कुल बाइट्स है।

यहां वास्तविक उत्पादन तालिका का एक उदाहरण दिया गया है

| ENGINE | TABLE_NAME               | data_length | index_length | data_free |
| InnoDB | comments                 |         896 |          316 |         5 |

इस मामले में हमारे पास एक तालिका का उपयोग करके (896 + 316) = 1212 एमबी है, और डेटा में 5 एमबी का निःशुल्क स्थान है। इसका अर्थ है "विखंडन का अनुपात":

5/1212 = 0.0041

... जो वास्तव में कम "विखंडन अनुपात" है।

मैं 0.2 (लगभग 20% रिक्त स्थान) के अनुपात के साथ तालिकाओं के साथ काम कर रहा हूं और प्रश्नों पर कभी धीमा नहीं पड़ता, भले ही मैं तालिका का अनुकूलन करता हूं, प्रदर्शन समान है। लेकिन 800MB की मेज पर एक अनुकूलन तालिका लागू करें बहुत समय लगता है और कई मिनटों के लिए तालिका को अवरुद्ध करता है, जो उत्पादन पर अव्यावहारिक है।

इसलिए, यदि आप विचार करते हैं कि आप प्रदर्शन में क्या जीतते हैं और समय एक टेबल को अनुकूलित करने में बर्बाद हो जाता है, तो मैं ऑप्टिमाइज़ नहीं करता।

यदि आपको लगता है कि भंडारण के लिए यह बेहतर है, तो अपना अनुपात देखें और देखें कि अनुकूलन करते समय आप कितनी जगह बचा सकते हैं। यह आमतौर पर बहुत अधिक नहीं है, इसलिए मैं ऑप्टिमाइज़ नहीं करना पसंद करता हूं।

और यदि आप अनुकूलन करते हैं, तो अगला अद्यतन एक पृष्ठ को दो या अधिक में विभाजित करके रिक्त स्थान बनाएगा। लेकिन यह खंडित तालिका को अपडेट करने के लिए तेजी से है न कि खंडित एक से, क्योंकि यदि तालिका खंडित है तो जरूरी नहीं कि एक पंक्ति में एक अद्यतन एक पृष्ठ को विभाजित करेगा।

मैं आशान्वित हूं कि इससे आपको सहायता मिलेगी।


1
हालाँकि यह कई साल पहले का उत्तर है, मैंने सोचा कि मैं बताऊँगा कि data_free पूरे टेबलस्पेस के लिए एक स्टेट है, न कि संबंधित टेबल के लिए। यदि आप एक टेबलस्पेस में एक साथ कई टेबल स्टोर करते हैं, तो डेटा_फ्री आपको यह विश्वास करने के लिए भ्रमित कर सकता है कि टेबल को डीफ़्रैग्मेंटिंग की आवश्यकता है, जब इसका मतलब है कि टेबलस्पेस में मुफ्त एक्स्टेंट हैं। ऑप्टिमाइज़िंग टेबल रन करने से फ्री एक्सटेंशन्स कम नहीं होंगे। टेबल को डीफ़्रैग्मेन्ट करने से फ्री एक्सटेंशन्स भी बढ़ सकते हैं।
बिल कारविन

14

फेलिप-रोजस से उत्तर में जोड़ने के लिए आप प्रश्न के भाग के रूप में अंश अनुपात की गणना कर सकते हैं:

select ENGINE,
  concat(TABLE_SCHEMA, '.', TABLE_NAME) as table_name,
  round(DATA_LENGTH/1024/1024, 2) as data_length,
  round(INDEX_LENGTH/1024/1024, 2) as index_length,
  round(DATA_FREE/1024/1024, 2) as data_free,
  (data_free/(index_length+data_length)) as frag_ratio
FROM information_schema.tables
WHERE DATA_FREE > 0
ORDER BY frag_ratio DESC;

यदि एक तालिका एक छोटा प्रतिशत (5% से कम) खंडित है, तो आप शायद इसे अकेले छोड़ सकते हैं।

कुछ भी बड़ा और आपको अपने डीबी उपयोग, तालिकाओं आदि के आधार पर आकलन करना होगा कि तालिका को डीफ़्रैग्मेंट करना कितना महत्वपूर्ण है।


2

ऑप्टिमाइज़ टेबल वास्तव में आपके पास होने वाली समस्या का समाधान करेगा।

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

यदि आपके पास बहुत सारे डेटाबेस हैं, तो एक और विधि संभवतः बेहतर होगी।

मैं हर घंटे चलाने के लिए क्रोन में निम्न PHP स्क्रिप्ट सेटअप का उपयोग करता हूं।

$DB = new mysqli ('localhost', 'DbUser', 'DbPassword');
$results = $DB->query('show databases');
$allDbs = array();
while ($row = $results->fetch_array(MYSQLI_NUM))
{
    $allDbs[] = $row[0];
}
$results->close();
foreach ($allDbs as $dbName)
{
    if ($dbName != 'information_schema' && $dbName != 'mysql')
    {
        $DB->select_db($dbName);
        $results = $DB->query('SHOW TABLE STATUS WHERE Data_free > 0');
        if ($results->num_rows > 0)
        {
            while ($row = $results->fetch_assoc())
            {
                $DB->query('optimize table ' . $row['Name']);
            }
        }
        $results->close();
    }
}
$DB->close();

3
मुझे पूरा यकीन है कि mysqlcheck --optimize -Aयह SQLOPTIMIZE TABLE <tablename>;
docwhat

2

मैं इस पृष्ठ पर आया और फेलिप-रोजस और सिसडमिरल के प्रश्नों को बहुत उपयोगी पाया। लेकिन मेरे मामले में, मैं WHM के phpMyAdmin में क्वेरी चला रहा था और केवल TABLE_NAME प्राप्त करना उतना उपयोगी नहीं था क्योंकि डेटाबेस सूचीबद्ध नहीं था, और कई डेटाबेस में समान तालिका नाम हैं। इसलिए, बस जोड़ने TABLE_SCHEMAसे वह कॉलम भी उपलब्ध होगा।

select  ENGINE, TABLE_SCHEMA, TABLE_NAME, Round( DATA_LENGTH/1024/1024) as data_length , round(INDEX_LENGTH/1024/1024) as index_length, round(DATA_FREE/ 1024/1024) as data_free, (data_free/(index_length+data_length)) as frag_ratio from information_schema.tables  where  DATA_FREE > 0 order by frag_ratio desc

डीबी दिखाता है

ENGINE  | TABLE_SCHEMA  | TABLE_NAME    | data_length   | index_length  | data_free | frag_ratio

InnoDB  | db_name       | db_table      | 0             | 0             | 8         | 170.6667

"ठीक" करने के लिए मैंने phpMyAdmin में प्रत्येक डीफ़्रेग्मेंट टेबल लिंक का उपयोग किया, जिसके परिणामस्वरूप उच्च "frag_ratio" हुआ जिसके लिए phpMyAdmin निष्पादित होता है:

ALTER TABLE `table_name` ENGINE = InnoDB;

0

MySQL के InnoDB इंजन का उपयोग करने वाली एक तालिका अनिवार्य रूप से कभी नहीं होनी चाहिए OPTIMIZEd

के मान Data_freeसे या तो information_schema.tablesया SHOW TABLE STATUSबहुत बार है गैर शून्य, तब भी जब आपको लगता है कि आप सभी आप अपनी तालिका (रों) defrag कर सकते हैं किया है। इसके अलावा, यह मीट्रिक केवल कई टुकड़ों में से एक है जो हो सकती है और होती है। (इसके अलावा, ब्लॉक, व्यर्थ सूचियों, इंडेक्स बीट्र्स बनाम डेटा बीट्रीस, आदि) में व्यर्थ जगह।

और innodb_file_per_tableके उपयोग को जटिल बनाता है Data_free। यदि तालिका अंदर है ibdata1, तो Data_freeपूरे टेबलस्पेस को संदर्भित करता है; बल्कि बेकार संख्या। यदि तालिका स्वयं की .ibdफ़ाइल में है, तो यह कुछ MB या कुछ प्रतिशत तालिका आकार की होने की संभावना है, जो भी बड़ा हो।

केवल अगर आपने बहुत सी पंक्तियाँ हटा दी हैं और तालिका को फिर से भरने का इरादा नहीं है, तो यह चलने लायक हो सकता है OPTIMIZE TABLE

PARTITIONsप्रत्येक विभाजन आमतौर पर 4-7MB "फ्री" दिखाता है Data_free, क्योंकि एक परेशान राशि भी दिखाता है । और यह नहीं चलेगा।

डीफ्रैगमेंट क्यों?

  • OS पर स्थान लौटने के लिए? ठीक है, आप इसे संक्षेप में प्राप्त कर सकते हैं यदि आपके पास था innodb_file_per_table=1। लेकिन जैसा कि आप पंक्तियों को जोड़ते हैं, आप इसे ओएस से वापस ले लेंगे।
  • पहुंच को गति देने के लिए? रहने भी दो। डिस्क पर ब्लॉक का लेआउट अपेक्षाकृत यादृच्छिक है, और पिछले कुछ दशकों से है। आधी सदी पहले, ब्लॉकों को पुनर्व्यवस्थित करना कुछ महत्वपूर्ण था।
  • बीट्रीस को पुनः संतुलित करने के लिए? इसलिए? वे तुरंत असंतुलित हो जाएंगे। बीटीएस के लिए स्थिर-अवस्था जो बेतरतीब ढंग से डाली जाती है, 69% है। और यह भी तथ्य नहीं है Data_free
  • MySQLTuner से कहता है? उस उत्पाद को ठंडा करने की आवश्यकता है।

एक इतिहास नोट। जब मैं ज्यादातर MyISAM तालिकाओं के साथ DBAs की मदद कर रहा था, तो मुझे पता चला कि 1000 में से 2 तालिकाएं थीं जिन्हें मासिक रूप से मदद की गई थी OPTIMIZE। तब से, मैंने हजारों InnoDB तालिकाओं के साथ काम किया है, अभी तक एक प्रदर्शन समस्या का पता लगाया है जिसकी मदद से संभव था OPTIMIZE। (निश्चित रूप से, डिस्क स्थान की समस्याएं हैं जिनके लिए OPTIMIZEमदद मिल सकती है, लेकिन यह मुश्किल हो जाता है - आमतौर पर डीबीए में चलने के लिए पर्याप्त स्थान नहीं होता है OPTIMIZE!)

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