欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MySQL下海量数据的迁移步骤分享

程序员文章站 2024-02-27 12:49:21
公司数据中心计划将海量数据做一次迁移,同时增加某时间字段(原来是datatime类型,现在增加一个date类型),单表数据量达到6亿多条记录,数据是基于时间(月)做的par...

公司数据中心计划将海量数据做一次迁移,同时增加某时间字段(原来是datatime类型,现在增加一个date类型),单表数据量达到6亿多条记录,数据是基于时间(月)做的partition由于比较忙,一直没有总结,所以很细节的地方都记不清楚了,此处只是简单总结下当时的情形,备忘

乱打乱撞

    最初接到任务,没有明确的入手点,直接就是select * from db limit 10000,动态修改翻页数量,通过控制台看耗时情况,慢

复制代码 代码如下:

select ir_sid,ir_hkey,ir_groupname,ir_sitename,ir_channel,ir_mid,ir_urlname,ir_status_content,ir_created_at,date_format(ir_created_at,'%y.%m.%d'),ir_lasttime,ir_via,ir_thumbnail_pic,ir_rttcount,ir_commtcount,ir_uid,ir_screen_name,ir_retweeted_uid,ir_retweeted_screen_name,ir_retweeted_mid,ir_retweeted_url,ir_status_body from tb_sina_status where ir_sid>40000 and ir_sid<50001 into outfile '/home/mysql/data/data_outfile.txt'; load data infile '/home/mysql/data/data_outfile.txt' into table new_tb_sina_status;

是否可以基于partition读数据呢

    既然数据库是按partition做分区,是否可以按partition读数据呢,如果可以改用怎样的语法读呢?时间上只要按月读数据,mysql会自动的基于partition读,具体可以用命令:explain partition即可看到具有基于哪个partition
    读大数据会十分耗时,对于数据进行到什么状态,我们可能十分想了解,可以用命令:show status查看,我印象中主要是sending data,writting to net之类的。
    innodb引擎的性能较myisam引擎到底如何?
    导库实验中导出并导入一个月的数据(8g的文本量,2500w条记录),在myisam引擎下需要不到4h(测试环境为pc机),但是在innodb引擎下,却需要32小时,改善索引之类的,也需要28h,性能有8倍之差。

    在网上找到了高人关于innodb与myisam区别,说需要修改innodb_buffer_pool_size、innodb_flush_log_at_trx_commit

可保证没有太大差别,尝试了没有明显改善,在本机倒是可以,为什么呢???这个折腾了我好长时间

innodb_flush_log_at_trx_commit

    是否为innodb比myisam慢1000倍而头大?看来也许你忘了修改这个参数了。默认值是 1,这意味着每次提交的更新事务(或者每个事务之外的语句)都会刷新到磁盘中,而这相当耗费资源,尤其是没有电池备用缓存时。很多应用程序,尤其是从 myisam转变过来的那些,把它的值设置为 2 就可以了,也就是不把日志刷新到磁盘上,而只刷新到操作系统的缓存上。日志仍然会每秒刷新到磁盘中去,因此通常不会丢失每秒1-2次更新的消耗。如果设置 为 0 就快很多了,不过也相对不安全了 — mysql服务器崩溃时就会丢失一些事务。设置为 2 只会丢失刷新到操作系统缓存的那部分事务。

innodb_buffer_pool_size

    innodb在默认的 innodb_buffer_pool_size 设置下跟蜗牛似的。由于innodb把数据和索引都缓存起来,无需留给操作系统太多的内存,因此如果只需要用innodb的话则可以设置它高达 70-80% 的可用内存。

    最后千辛万苦的、跋山涉水的,找到了另外两个参数

innodb_log_file_size

    在高写入负载尤其是大数据集的情况下很重要。这个值越大则性能相对越高,但是要注意到可能会增加恢复时间。我经常设置为 64-512mb,跟据服务器大小而异。

innodb_log_buffer_size
    默认的设置在中等强度写入负载以及较短事务的情况下,服务器性能还可以。如果存在更新操作峰值或者负载较大,就应该考虑加大它的值了。如果它的值设置太高了,可能会浪费内存 — 它每秒都会刷新一次,因此无需设置超过1秒所需的内存空间。通常 8-16mb 就足够了。越小的系统它的值越小。


最终搞定,myisam与innodb的导数据的性能基本一致,2500的数据约需要3.5h,单库读数据需要2h,这个只是一个示意值仅供参考(pc上的测试),正式服务的上的测试结果更加明显

性能调优语句参考

复制代码 代码如下:

set profiling = 1;
show profiles\g
show profile cpu,block io io for query 1;
show status
show processlist
explain

并行读取是否会更快?

如果基于partition导数据,还是不能达到既定目标,我最终是通过编写shell脚步,多进程并行基于partition导数据,即启动多个mysql -uroot -p db < exp201201.sql 、mysql -uroot -p db < exp201202.sql,每个sql下按天做读写(事件环境下是按月做partition的)

复制代码 代码如下:

select ir_sid,ir_hkey,ir_groupname,ir_sitename,ir_channel,ir_mid,ir_urlname,ir_status_content,ir_created_at,date_format(ir_created_at,'%y.%m.%d'),ir_lasttime,ir_via,ir_thumbnail_pic,ir_rttcount,ir_commtcount,ir_uid,ir_screen_name,ir_retweeted_uid,ir_retweeted_screen_name,ir_retweeted_mid,ir_retweeted_url,ir_status_body
into outfile '/home/mysql/data/sinawb20120724/111101.txt'
fields terminated by ',' optionally enclosed by '"' escaped by '\\'
lines terminated by '\n'
from tb_sina_status 
where ir_created_at >='2011-11-01 00:00:00' and ir_created_at <'2011-11-01 23:59:59'

load data  local infile '/home/mysql/data/sinawb20120724/111101.txt'
ignore into table `new_tb_sina_status`
character set utf8 
fields terminated by ',' optionally enclosed by '"' escaped by '\\'
lines terminated by '\n'