Bir MySQL tablosunda yaklaşık 40 milyon satır var ve bu tabloyu aynı veritabanındaki başka bir tabloya kopyalamak istiyorum. Bunu yapmanın en etkili yolu nedir? Ne kadar zaman alacak (yaklaşık)?
Bir MySQL tablosunda yaklaşık 40 milyon satır var ve bu tabloyu aynı veritabanındaki başka bir tabloya kopyalamak istiyorum. Bunu yapmanın en etkili yolu nedir? Ne kadar zaman alacak (yaklaşık)?
Yanıtlar:
Sahip olduğunuzu mydb.mytb
ve oluşturmak istediğinizi varsayalımmydb.mytbcopy
Bu kopyayı yapmak için beş (5) yaklaşımım var
Gelen mysql
müşteri, aşağıdaki çalıştırmak
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
Zaten var olan bir tabloya kopyalamak istiyorsanız mydb.mytbcopy
ve iki tablonun özdeş yapıları vardır:
INSERT INTO mytbcopy SELECT * FROM mytb;
Gibi #APPROACH 1 , #APPROACH 6 40000000 satır tek bir işlem olurdu
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
Bu yaklaşımlar masayı düşürmez. Yalnızca INSERT'leri oluşturur
DB Server, tablo yapısı, dizin düzeni ve bunun gibi şeyler bilmiyorum çünkü size bir zaman tahmini veremem.
InnoDB tabloları, MyISAM * 'dan farklı olarak, veri sözlüğünün bir parçası olarak (ve birleştirme arabelleği gibi tablonun bağlı olduğu diğer yapılar) bellekte (sunucu çalışıyorsa) ve ortak / ana tablo alanı, diğer adı verilen büyük dosya ibdata1
.
Percona Server> = 5.1 veya MySQL> = 5.6 kullanıyorsanız, tabloları doğrudan dosya sisteminden dışa ve içe aktarmanıza izin veren taşınabilir tablo alanları desteği vardır. İşte MySQL ve Percona için yöntem . Her iki durumda da, innodb_file_per_table
seçeneği içeren bir tablo oluşturmuş olmanız DISCARD TABLESPACE/IMPORT TABLESPACE
ve / veya Percona Xtrabakup'ın kullanımını içermeniz gerekir (dışa aktarmanın çevrimiçi olarak yapılmasını istiyorsanız). Percona Server veya Xtrabakup'un Windows için mevcut olmadığını lütfen unutmayın.
Bu yöntem, genel olarak, dosya sistemi komutlarını (cp, rsync) kullanarak dosyayı kopyalamak kadar hızlı olacaktır .
Geri yükleme için MySQL <5.6 (hacky bir şekilde) 'de çalışabileceği bazı durumlar olsa da, bir tablo kopyası için çalışmayacaktır. Bu durumlarda, bunu yapmanın bir yolu SQL kullanmaktır :
CREATE TABLE new_table LIKE old_table;
INSERT INTO new_table SELECT * FROM old_table;
Bu, InnoDB'nin yürütebileceği kadar hızlı Handler_read_rnd_next
ve Handler_write
her satırda bir kez olacaktır. Bu yöntemi kullanırsanız, dayanıklılık seçeneklerini en azından geçici olarak devre dışı bıraktığınızdan ve büyük bir arabellek havuzunuz ve işlem günlüğünüz olduğundan emin olun. Bu koşullar altında, içe aktarma süresini azaltabilir, ancak kesinlikle belleğe tam olarak sığmaz, bu yüzden çok zaman bekleyin. Ayrıca, tek bir işlemde 40M satırları almaya çalışıyorsunuz, bu da sorunlara yol açabilir.
Gerçek tavsiyem, bu ikinci durumda, az önce bahsettiğim gibi bir işlem gerçekleştireceğinden, pt-archiver gibi bir şey kullanmak olacaktır, ancak işlem yükünü önleyerek "parçalar" halinde yapılacaktır ( daha hızlı olmamalı, ancak bir hata durumunda, tüm masayı geri almaya çalışmayacak, sonsuza dek sürecek). Bahsettiğiniz veri boyutları için bu muhtemelen en iyi yoldur.
Son seçenek, SELV INF OUTFILE / mysqldump ve LOAD DATA / mysqlimport kombinasyonu ile CSV (veya TSV) biçimini kullanarak dışa ve içe aktarmak olacaktır . Mysql'nin bazı eski sürümlerinde eşzamanlılık gerekiyorsa bu çok yaygın bir seçimdi, çünkü sql kullanmak daha büyük kilitler oluşturdu (doğru yapılırsa artık doğru değil). Mysqldump / import sadece serileştirilmiş bir şekilde çalıştığından, paralelleştirmek için seçenekleri araştırmanızı öneririm, büyük tablolar için çok yararlı.
Her durumda, çok sayıda farklı sorgu yürütmeniz (tek tek yürütülmesi, ayrıştırılması ve optimize edilmesi gerekir) en önemli darboğazınız olacağından, birden çok SQL cümlesinden kaçınmaya çalışın.
* MyISAM yapıları sıcak bir şekilde kopyalanamaz, ancak bunları geçici olarak diske senkronize etmek çok kolaydır FTWRL
.
şemadaki verileri bir tablodan diğerine taşıma
create table your_table_name select * from old_schema_table;