MyISAM का InnoDB में तेजी से रूपांतरण


15

मुझे लगभग 450 टेबलों के डेटाबेस के साथ एक mysql 5.1 सर्वर मिला है, जिसमें 4GB है। इन तालिकाओं के विशाल बहुमत (सभी लेकिन 2) MyIsam हैं। यह अधिकांश भाग के लिए ठीक है (लेन-देन की आवश्यकता नहीं है), लेकिन एप्लिकेशन ट्रैफ़िक प्राप्त कर रहा है और अपडेट पर टेबल-लॉकिंग के कारण कुछ टेबल प्रभावित हुए हैं। यही कारण है कि तालिकाओं के 2 अब InnoDB हैं।

छोटे तालिकाओं (100k पंक्तियों) पर रूपांतरण को कम से कम समय नहीं लगता है। हालाँकि मेरी कुछ ट्रैकिंग तालिकाएँ 50 मिलियन पंक्तियों तक पहुँच रही हैं। क्या ALTER TABLE...ENGINE InnoDBबड़े तालिकाओं पर तेजी लाने का एक तरीका है ? और यदि नहीं, तो क्या इन लेखन-भारी तालिकाओं पर डाउनटाइम को परिवर्तित करने के लिए अन्य तरीके हैं?


1
कुछ ध्यान में रखना: एक ही पोस्ट में कई सवाल उन लोगों को हतोत्साहित करते हैं जो किसी एक सवाल का जवाब पोस्ट करने से दे सकते हैं।
बेनवी

I VtC क्योंकि यह उत्तर देने के लिए जटिल है। आपको व्यक्तिगत रूप से कई प्रश्नों को खोलना चाहिए।
jcolebrand

मैं ख़ुशी से इसे एक एकल प्रश्न बनाने की सलाह दूंगा, लेकिन क्या इस प्रश्न को हटाने और केवल एक नया खोलने की सिफारिश की गई है? फिर से लिखना ज्यादातर दूसरी 2 गोलियों को हटा देगा और पहले को बदल देगा (मैंने शीर्षक को अद्यतन करने के साथ-साथ यह भी बताया कि कौन से भंडारण इंजन हैं)
डेरेक डाउनी

या तो ठीक होगा। आमतौर पर दो अन्य प्रश्न लिखना और एक को हटाना आसान होता है । हालाँकि, आप इसे आसानी से "संदर्भ" के लिए छोड़ सकते हैं और अन्य दो को वापस संदर्भित कर सकते हैं, "यह मेरा समग्र लक्ष्य है" प्रश्न के रूप में।
jcolebrand

इसे नीचे एक बुलेट में संपादित करें, फिर अनुवर्ती प्रश्न पोस्ट करें।
बजे ब्रायन बॉसुन-स्टैंटन

जवाबों:


10

मुझे कहने से शुरू करें, मुझे ALTER से नफरत है। यह बुरा है, IMHO।

कहो, यह आपकी वर्तमान तालिका स्कीमा है -

CREATE TABLE my_table_of_love (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
my_value VARCHAR(40),
date_created DATE,
PRIMARY KEY(id)
) ENGINE=MyISAM CHARSET=utf8;

यहाँ मेरा सुझाव है -

एक नया टेबल ऑब्जेक्ट बनाएं जो पुराने को बदल देगा:

CREATE TABLE my_table_of_love_NEW (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
my_value VARCHAR(40),
date_created DATE,
PRIMARY KEY(id)
) ENGINE=InnoDB CHARSET=utf8

नई तालिका में नाम से पुरानी तालिका से सभी पंक्तियाँ सम्मिलित करें:

INSERT INTO my_table_of_love_NEW (id,my_value,date_created)
SELECT id,my_value,date_created FROM my_table_of_love;

धुआँ परीक्षण अपने प्रवास:

SELECT COUNT(*) FROM my_table_of_love_NEW;
SELECT COUNT(*) FROM my_table_of_love;
SELECT a.id,a.my_value,a.date_created FROM my_table_of_love_NEW a
LEFT JOIN my_table_of_love b ON (b.id = a.id)
WHERE a.my_value != b.my_value;

तालिका का नाम स्वैप करें ताकि आप रोलबैक करने की आवश्यकता होने पर बैक अप बनाए रख सकें।

RENAME TABLE my_table_of_love TO my_table_of_love_OLD;
RENAME TABLE my_table_of_love_NEW TO my_table_of_love;

प्रतिगमन परीक्षण के लिए आगे बढ़ें।

यह दृष्टिकोण कई अनुक्रमित और लाखों पंक्तियों के साथ तालिकाओं के साथ अधिक बेहतर होता है।

विचार?


1
सहमत ... हालांकि अगर यह भारी लेनदेन है, तो आपको ऐसा करते समय डेटाबेस को नीचे ले जाना पड़ सकता है। (लेकिन एक परिवर्तन तालिका आपको डाउनटाइम की एक लंबी अवधि देने के लिए जा रही है, सबसे अधिक संभावना है)
जो

हाँ, मुझे लगा कि इसे अधिक सक्रिय तालिकाओं के लिए डाउनटाइम की आवश्यकता होगी। मुझे कुछ परीक्षण चलाने होंगे, लेकिन 50 मिलियन पंक्तियों की ALTER TABLEतुलना में अधिक समय क्यों लगेगा INSERT INTO...SELECT?
डेरेक डाउनी

यह नहीं होगा मूल रूप से MySQL आंतरिक रूप से वैसा ही करता है जैसा कि इस पोस्टर ने सुझाया था। यह परिभाषा की एक प्रति बनाता है और ट्रिकल लोड की प्रतिलिपि बनाता है।
Morgan Tocker

मुझे यह तरीका पसंद है क्योंकि यह "कॉपी टू टीएमपी" भाग को छोड़ देता है, जिसमें बड़ी तालिकाओं के लिए कुछ समय लग सकता है।
हलुक

मुझे अभी जोड़ना है, कि MySQL 5.7 में, ALTERs बहुत तेजी से और आसानी से सामना कर रहे हैं।
रैंडमक्स

7

1) हानि संरक्षण व्यामोह का एक कार्य है। हमेशा एक बैकअप बनाएं। यदि आप वास्तव में पागल हैं, तो एक बैकअप बनाएं और फिर बैकअप से पुनर्स्थापित करें।

2) MySQL मैनुअल के इस पृष्ठ में तालिका प्रकारों को परिवर्तित करने के निर्देश हैं।

InnoDB में तालिका को बदलने का सबसे तेज़ तरीका आवेषण सीधे एक InnoDB तालिका में करना है। अर्थात, ALTER TABLE ... इंजन = INNODB का उपयोग करें, या समान परिभाषाओं के साथ एक खाली InnoDB तालिका बनाएं और INSERT INTO ... SELECT * FROM ... के साथ पंक्तियाँ डालें।

3) PostgreSQL पूर्ण-पाठ खोज करता है , Sphinx इंजन इसे MySQL के लिए करता है


मैं निश्चित रूप से स्फिंक्स में देखूंगा, जैसा कि मैंने हाल ही में इसके बारे में सुना है।
डेरेक डाउनी

3

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

मैं आपको स्पिनक्स , ल्यूसिन ( सोल ) जैसे कुछ समर्पित पूर्ण पाठ खोज इंजनों में रुचि रखने और डेटाबेस लेयर से छुटकारा पाने की सलाह देता हूं ।

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