InnoDB तालिका से स्थान हटाना और पुनः प्राप्त करना


14

मेरे पास एक 700GB InnoDB टेबल है जिसे मैं (केवल पढ़ने के लिए) कोई और डेटा नहीं लिख रहा हूं। मैं अपने पास मौजूद पुराने डेटा को हटाना चाहता हूं और उस डिस्क स्थान को पुनः प्राप्त करना चाहता हूं (जैसा कि मैं इससे बाहर चल रहा हूं)। डिलीट पार्ट बहुत आसान है, क्योंकि मेरे पास एक ऑटो-इंक प्राइमरी इंडेक्स है, इसलिए मैं इसे इस्तेमाल करने वाले चंक्स में केवल पुनरावृति कर सकता हूं, और पंक्तियों को हटा सकता हूं, लेकिन यह मुझे अंतरिक्ष में वापस नहीं लाएगा। मुझे लगता है OPTIMIZE TABLEकि लेकिन यह एक 700GB मेज पर हमेशा के लिए ले जा सकता है, तो वहाँ एक और विकल्प मैं देख रहा हूँ?

RolandoMySQLDBA द्वारा संपादित करें

मान लें कि आपकी तालिका mydb.mytableनिम्न है , कृपया निम्न क्वेरी को चलाएँ और इसे यहाँ पोस्ट करें ताकि आप तालिका के सिकुड़ने के लिए आवश्यक डिस्कस्पेस निर्धारित कर सकें:

SELECT
    FORMAT(dat/POWER(1024,3),2) datsize,
    FORMAT(ndx/POWER(1024,3),2) ndxsize,
    FORMAT((dat+ndx)/POWER(1024,3),2) tblsize
FROM (SELECT data_length dat,index_length ndx
FROM information_schema.tables WHERE
table_schema='mydb' AND table_name='mytable') A;

यदि आवश्यक हो, तो हमें तालिका संरचना को भी देखना होगा।

नोआम द्वारा संपादित

यह क्वेरी का आउटपुट है:

datsize ndxsize tblsize
682.51 47.57 730.08

यह तालिका संरचना है ( SHOW CREATE TABLE)

`CREATE TABLE `mybigtable` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL,  
  `created_at` datetime NOT NULL,  
  `tid` bigint(20) NOT NULL,  
  `text` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
  `ft` tinyint(1) NOT NULL,  
  `irtsd` bigint(20) NOT NULL,  
  `irtuid` int(11) NOT NULL,  
  `rc` int(11) NOT NULL,  
  `r` tinyint(1) NOT NULL,  
  `e` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,  `timezone` varchar(5) NOT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `uid_tid` (`uid`,`tid`)) ENGINE=InnoDB AUTO_INCREMENT=2006963844 DEFAULT CHARSET=utf8`

क्या आपके पास केवल डेटा को पकड़ने के लिए एक और डिस्क वॉल्यूम है ???
रोलैंडमाइसीडीडीबीए

@RolandoMySQLDBA मेरे पास एक बाहरी हार्ड-ड्राइव है जिसे मैं माउंट कर सकता हूं। क्या वह माना जाएगा?
नोम

@RolandoMySQLDBA लेकिन एक विकल्प की तरह कुछ जगह को हटाने के लिए एक विकल्प की तरह होगा एक और 700GB
Noam

@RolandoMySQLDBA अतिरिक्त डिस्क आकार किसी भी प्रदर्शन समस्याओं का कारण बनता है?
अरीस

@ यह डिस्क और उसके समय के आधार पर हो सकता है। इन दिनों, अधिकांश डिस्क अब बेहतर प्रदर्शन करते हैं, लेकिन क्या अच्छा है जो चक्र को बर्बाद कर रहा है (यहां तक ​​कि वास्तव में तेजी से जा रहा है) यदि आपके टेबल में डिस्कस्पेस के बड़े विरल जेब हैं ??? यह विशेष रूप से InnoDB के लिए सच है जो आम तौर पर 16K ब्लॉकों पर तय की जाती है। 16K ब्लॉकों के आंतरिक विखंडन के साथ, आप तालिका का उपयोग करके डीफ़्रैग्मेन्ट करना चाह सकते हैं ALTER TABLE ... ENGINE=InnoDB;(यदि आपको ऐसा करने के लिए कमरा मिला है)। ज्यादातर अपने बहुत तेज SSD से संतुष्ट हैं और चिंता नहीं करेंगे।
रोलैंडमाइसीडीडीबीए

जवाबों:


21

यह अच्छा प्रश्न है। आपके पास कई समाधान हैं लेकिन आपकी तालिका काफी बड़ी है इसलिए कोई भी दर्द के बिना नहीं होगा :)

आपके पास InnoDB तालिकाओं को "सिकोड़ने" के लिए तीन समाधान हैं:

1. वैकल्पिक टेबल

आप इसका OPTIMIZE TABLEउल्लेख करते हुए उपयोग कर सकते हैं लेकिन आपको innodb_file_per_tableचर की परवाह करनी चाहिए :

mysql> show variables like "innodb_file_per_table";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)

मुझे समझाने दो:

OPTIMIZE TABLEWhith InnoDB टेबल, मेज ताले, एक नया स्वच्छ तालिका (यही कारण है कि परिणाम shrinked है), मूल तालिका ड्रॉप और मूल नाम के साथ नई तालिका का नाम बदलने में डेटा की प्रतिलिपि। इसीलिए आपको अपने डिस्क में उपलब्ध टेबल की दोगुनी मात्रा का ध्यान रखना चाहिए (ऑपरेशन के दौरान आपको 2x700GB की आवश्यकता होगी)।

जब आप innodb_file_per_table = ON में हैं। सभी तालिकाओं में यह उचित डेटा फ़ाइल है। इसलिए OPTIMIZEबयान एक नई डेटा फ़ाइल (~ 700GB) बनाएगा जब ऑपरेशन खत्म हो जाएगा, MySQL मूल को छोड़ देगा और नए को फिर से नाम देगा (इसलिए अंत में 700GB - शायद कम है क्योंकि यह सिकुड़ जाएगा - डेटा का ऑपरेशन के दौरान उत्पन्न

जब आप innodb_file_per_table = OFF में हैं। सभी डेटा एक डेटा फ़ाइल में जाता है: ibdata । इस फ़ाइल की एक ख़ासियत है, इसे छोटा नहीं किया जा सकता है। इसलिए इस OPTIMIZEप्रक्रिया के दौरान , आपकी नई तालिका (700GB के पास) बनाई जाएगी, लेकिन ड्रॉप और नाम बदलने के संचालन (और OPTIMIZEचरण के अंत ) के बाद भी आपकी ibdata ~ 700GB जारी नहीं होगी, इसलिए आप कुछ डेटा मुफ्त चाहते थे लेकिन आपके पास 700GB है अधिक, अच्छा है ना?

2. वैकल्पिक तालिका

आप एक ALTER TABLEबयान का उपयोग भी कर सकते हैं , ALTER TABLEउसी तरह से काम करेगा OPTIMIZE TABLE। आप बस उपयोग कर सकते हैं:

ALTER TABLE myTable EGINE=InnoDB;

3. वैकल्पिक तालिका (ऑनलाइन)

की समस्या OPTIMIZEऔर ALTER TABLEयह ऑपरेशन के दौरान टेबल को लॉक कर देती है। आप Percona टूल का उपयोग कर सकते हैं: pt-online-schema-change (Percona टूलकिट से: लिंक )। पीटी-ऑनलाइन-स्कीमा ... ट्रिगर्स और टेंपरेचर टेबल के साथ एक मेकेनिज्म का निर्माण करेगा जिसे आप ऑपरेशन के दौरान मूल तालिका को पढ़ने और लिखने के लिए उपलब्ध होने की अनुमति देते हैं। मैं इस उपकरण का उपयोग बड़े ALTERशांत के लिए करता हूं ।

ध्यान दें कि आपको FOREIGN KEYअपनी तालिका, FK को संदर्भित करना चाहिए और एक गड़बड़ पैदा करने के लिए जोखिम को ट्रिगर करता है। इस शर्त को जांचने के लिए, प्रश्न:

mysql> SELECT COUNT(*) FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE REFERENCED_TABLE_NAME = "myTable";
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+
1 row in set (0.04 sec)

यहां बताया गया है कि मैं pt-online-schema-change का उपयोग कैसे करता हूं:

pt-online-schema-change --alter "ENGINE=InnoDB" D=myBase,t=myTable --user --ask-pass

ध्यान दें कि इस समाधान के लिए innodb_file_per_table पर मेरा नोट भी सही है।

4. mysqldump

अंतिम समाधान एक डंप से सभी डेटाबेस को फिर से बनाना है। बहुत लंबा है, लेकिन बहुत कुशल है। ध्यान दें कि यह ibdata फ़ाइल को "सिकोड़ने" का एकमात्र समाधान है।

मैक्स।


इसके अलावा पर्कॉन टूल ऑनलाइन चेंज टेबल विकल्प में मुझे 700GB मुफ्त डिस्क स्थान की आवश्यकता होगी?
नोआम

हाँ, pt-online सिर्फ ALTER ऑनलाइन करने के लिए कुछ mecanism का उपयोग करते हैं, लेकिन यह वैसे भी ALTER बनाता है।
मैक्सिमे फौइउल

@MaximeFouilleul क्या अतिरिक्त डिस्क आकार किसी भी प्रदर्शन समस्याओं का कारण बनता है?
एरिस

1

यदि आप डिस्क आकार में छोटे हैं, तो मैं आपको उसी तरह करना चाहूंगा, जैसे कि pt-online-schema-change (ONLINE) के साथ सुझाए गए अधिकतम। मैं एक बहुत छोटी तालिका (200GB) के साथ एक ही स्थिति में रहा हूं और एक ही समय में कुछ संपीड़न करना चुना। इस की तर्ज पर कुछ काम करना चाहिए:

pt-online-schema-change --alter="ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4" D=myBase,t=myTable --user --ask-pass

यह केवल तभी काम करेगा जब आप बाराकुडा फ़ाइल प्रारूप और तालिका के COMPACT प्रारूप में हों। इसके अलावा आपके पास innodb_file_per_table सक्षम होना चाहिए। यह आपकी तालिका के आकार पर चमत्कार कर सकता है, खासकर अगर बहुत अधिक पाठ हो और यदि आप छोटे KEY_BLOCK_SIZE जैसे 8K या 4K का उपयोग करते हैं (डिफ़ॉल्ट 16K है)। आप यह भी जांच सकते हैं कि अन्य ब्लॉग पर इस मुद्दे के बारे में आप कई बेंचमार्क से कितना स्थान प्राप्त कर सकते हैं, लेकिन MySQL प्रलेखन 25% से 50% तक विज्ञापन करता है (यह मेरे लिए लगभग 90% था)।

ध्यान दें कि यह चयन (MySQL प्रलेखन से) करते समय प्रदर्शन को भी प्रभावित कर सकता है:

इस प्रकार, किसी भी समय, बफर पूल में पृष्ठ के संपीड़ित और असम्पीडित दोनों प्रकार हो सकते हैं, या केवल पृष्ठ का संकुचित रूप हो सकता है, या न ही।

जब बफर पूल में नहीं होता है तो MySQL को डेटा को अनकैप्ड करना पड़ता है। इसलिए चेतावनी दी जाए।

यह वास्तव में मेरे मामले में ठीक काम किया है। मेरे पास एक लंबा पाठ था। 200GB 26GB बन गया। प्रदर्शनों में फेरबदल नहीं किया गया।

अधिक जानकारी के लिए इन लिंक्स की जाँच करें:

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-usage.html

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-internals.html

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