मेरे पास एक MySQL तालिका में लगभग 40 मिलियन पंक्तियाँ हैं और मैं इस तालिका को उसी डेटाबेस में किसी अन्य तालिका में कॉपी करना चाहता हूं। ऐसा करने का सबसे कुशल तरीका क्या है? कितना समय लगेगा (लगभग)।
मेरे पास एक MySQL तालिका में लगभग 40 मिलियन पंक्तियाँ हैं और मैं इस तालिका को उसी डेटाबेस में किसी अन्य तालिका में कॉपी करना चाहता हूं। ऐसा करने का सबसे कुशल तरीका क्या है? कितना समय लगेगा (लगभग)।
जवाबों:
मान लीजिए आपके पास है mydb.mytb
और आप बनाना चाहते हैंmydb.mytbcopy
इस प्रति को करने के लिए मेरे पास पाँच (5) दृष्टिकोण हैं
में mysql
ग्राहक, निम्नलिखित चलाने
USE mydb
CREATE TABLE mytbcopy LIKE mytb;
INSERT INTO mytbcopy SELECT * FROM mytb;
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysql ${MYSQL_CONN} -ANe"CREATE DATABASE IF NOT EXISTS test"
mysqldump ${MYSQL_CONN} mydb mytb | mysql ${MYSQL_CONN} -Dtest
mysql ${MYSQL_CONN} -ANe"ALTER TABLE test.mytb RENAME mydb.mytbcopy"
DUMPFILE=/some/path/tabledata.sql
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysql ${MYSQL_CONN} -ANe"CREATE DATABASE IF NOT EXISTS test"
mysqldump ${MYSQL_CONN} mydb mytb > ${DUMPFILE}
mysql ${MYSQL_CONN} -Dtest < ${DUMPFILE}
rm -f ${DUMPFILE}
mysql ${MYSQL_CONN} -ANe"ALTER TABLE test.mytb RENAME mydb.mytbcopy"
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysqldump ${MYSQL_CONN} mydb mytb | sed 's/mytb/mytbcopy' | mysql ${MYSQL_CONN} -Dmydb
DUMPFILE=/some/path/tabledata.sql
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysqldump ${MYSQL_CONN} mydb mytb | sed 's/mytb/mytbcopy' > ${DUMPFILE}
mysql ${MYSQL_CONN} -Dmydb < ${DUMPFILE}
rm -f ${DUMPFILE}
यदि आप mydb.mytb
पहले से मौजूद तालिका में प्रतिलिपि बनाना चाहते हैं mydb.mytbcopy
, और दो तालिकाओं में समान संरचनाएँ हैं:
INSERT INTO mytbcopy SELECT * FROM mytb;
#APPROACH 1 की तरह , #APPROACH 6 में 40 मिलियन पंक्तियों का एक ही लेन-देन होगा
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysqldump ${MYSQL_CONN} -t mydb mytb | sed 's/mytb/mytbcopy' | mysql ${MYSQL_CONN} -Dmydb
यह दृष्टिकोण तालिका को नहीं गिराता है। यह केवल INSERTs उत्पन्न करता है
मैं आपको एक समय का अनुमान नहीं दे सकता क्योंकि मुझे डीबी सर्वर, टेबल संरचना, सूचकांक लेआउट और इन जैसी चीजों का पता नहीं है।
इनसबीडी टेबल, माईसैम * के विपरीत, "बस दूर कॉपी किया जा सकता है", इसके डेटा डिक्शनरी के भाग के रूप में (और संभावित रूप से अन्य संरचना तालिका के आधार पर, मर्ज बफर की तरह) मेमोरी में स्थित हैं (यदि सर्वर चल रहा है) और में आम / मुख्य टेबलस्पेस, उर्फ जिसे बड़ी फाइल कहा जाता है ibdata1
।
यदि आप Percona Server> = 5.1 या MySQL> = 5.6 का उपयोग कर रहे हैं, तो ट्रांसपोर्टेबल टेबलस्पेस के लिए समर्थन है, जो आपको फाइल सिस्टम से सीधे टेबल को निर्यात और आयात करने की अनुमति देता है। यहाँ यह MySQL के लिए और Percona के लिए विधि है । दोनों मामलों में, यह आवश्यक है कि आपने innodb_file_per_table
विकल्प के साथ तालिका बनाई थी और इसमें DISCARD TABLESPACE/IMPORT TABLESPACE
/ और पेरकोना Xtrabakup (यदि आप चाहते हैं कि निर्यात ऑनलाइन किया जाए) का उपयोग शामिल है। कृपया ध्यान दें कि विंडोज के लिए पेरकोना सर्वर या Xtrabakup उपलब्ध नहीं हैं।
यह विधि सामान्य रूप से बोल रही होगी, जितनी तेजी से फाइलसिस्टम कमांड (cp, rsync) का उपयोग करके फाइल को कॉपी किया जाएगा ।
हालांकि कुछ मामले हो सकते हैं कि यह MySQL <5.6 (एक हैक तरीके से) में पुनर्स्थापित करने के लिए काम कर सकता है, यह एक टेबल कॉपी के लिए काम नहीं करेगा। उन मामलों में, SQL का उपयोग करके ऐसा करने का एक तरीका है :
CREATE TABLE new_table LIKE old_table;
INSERT INTO new_table SELECT * FROM old_table;
यह उतनी ही तेजी से होगा जितना कि InnoDB निष्पादित कर सकता है Handler_read_rnd_next
और Handler_write
, एक बार प्रति पंक्ति। यदि आप इस विधि का उपयोग करते हैं, तो सुनिश्चित करें कि आप अक्षम, कम से कम अस्थायी रूप से, स्थायित्व विकल्प और आपके पास एक बड़ा बफर पूल और लेनदेन लॉग है। उन परिस्थितियों में, यह आयात करने के समय को कम कर सकता है, लेकिन यह निश्चित रूप से पूरी तरह से स्मृति में फिट नहीं होगा, इसलिए बहुत समय की अपेक्षा करें। इसके अलावा, आप एक ही लेनदेन में 40M पंक्तियों को आयात करने की कोशिश कर रहे हैं, जिससे समस्या हो सकती है।
मेरी वास्तविक सिफारिश, इस दूसरे मामले में, pt-archiver जैसी किसी चीज़ का उपयोग करने की होगी , क्योंकि यह मेरे द्वारा बताए गए के समान एक ऑपरेशन करेगा, लेकिन यह "विखंडन" में किया जाएगा, लेन-देन ओवरहेड से बचने के लिए (यह हो सकता है) तेजी से नहीं, लेकिन एक विफलता के मामले में, यह पूरी मेज को रोलबैक करने की कोशिश नहीं करेगा, हमेशा के लिए)। आपके द्वारा उल्लिखित डेटा आकारों के लिए, यह संभवतः जाने का सबसे अच्छा तरीका है।
एक अंतिम विकल्प CSV (या TSV) प्रारूप का उपयोग करके निर्यात और आयात करना होगा , जिसमें SELECT INTO OUTFILE / mysqldump और LOAD DATA / mysqlimport का संयोजन होगा। यह एक बहुत ही आम विकल्प था यदि आपको mysql के कुछ पुराने संस्करणों में संगामिति की आवश्यकता होती है, क्योंकि sql ने बड़े तालों का उपयोग किया है (यदि सही तरीके से नहीं किया गया है तो सच है)। जैसा कि mysqldump / import केवल क्रमबद्ध तरीके से काम करता है, मैं आपको इसे बड़ा करने के लिए अनुसंधान विकल्पों की सिफारिश करूंगा, बड़ी तालिकाओं के लिए बहुत उपयोगी।
किसी भी स्थिति में, कई SQL वाक्यों से बचने की कोशिश करें, क्योंकि यह आपकी सबसे महत्वपूर्ण अड़चन होगी यदि आप कई अलग-अलग प्रश्नों को निष्पादित करते हैं (जो कि व्यक्तिगत रूप से निष्पादित, पार्स और अनुकूलित किए जाने हैं)।
* MyISAM संरचनाओं को एक गर्म तरीके से कॉपी नहीं किया जा सकता है, लेकिन उन्हें डिस्क के साथ अस्थायी रूप से सिंक करना बहुत आसान है FTWRL
।
स्कीमा में डेटा को एक टेबल से दूसरी में ले जाना
create table your_table_name select * from old_schema_table;