Loading...

Tag Archive for '%e6%95%b0%e6%8d%ae%e8%bf%81%e7%a7%bb'

    AD: 猛买网,精彩团购 | Jobsdigg | 很棒的男装店 | 网站地图

数据迁移心得(1) -在rails之外操作数据

最近我手中一个rails项目行将完成,于是面临着从原有项目迁移数据到新项目的任务。原来的系统数据库设计和新的设计差别比较大,编码也从gbk变成了utf8,所以迁移的过程免不了,而且要涉及到将近七百万条数据。
给自己做东西,也懒得用什么rest。后来就在后台某控制器内直接写了个import的方法,限制用post提交所有数据并且使用一个校验码以保证安全,之后处理入库。这个没啥难度,在rails里面就是一个new、一个save,关键是要快。
于是需要一个脚本从旧数据库中读出数据,进行必要的组合,然后提交到导入的URL。脚本选择用ruby来写,用着趁手,所以需要在ruby中访问数据库,用拼凑出来的sql去获得数据。这可以在rails之外,对ruby有个深入了解。
想借用active record的connection,所以首先需要
require ‘active_record’
之后连接数据库:
ActiveRecord::Base.establish_connection(
:adapter => ‘mysql’,  :database=>’db_name’, :user=>’username’ , :password=>’password’
)
这个相当于php中的mysql_connect。之后想要执行sql语句,都可以通过ActiveRecord::Base.connection这个对象的execute方法来进行。在irb中查看就知道这是个MysqlAdapter对象。数据迁移要进行编码转换,原来是GBK编码,所以需要先设置一句:
ActiveRecord::Base.connection.execute(“set names ‘utf8′ “)
这样mysql会自动把gbk编码转换为utf8,关于编码的问题其实比较复杂,这个以后讨论。在这里只要这样一句,取出来的中文就是utf8了,没有任何问题。
进行查询,还是execute:
res = ActiveRecord::Base.connection.execute(“select  * from xxx”)
得到的res是一个Mysql::Result类的实例。在php中,用mysql_query得到结果以后可以有fetch_row/fetch_arrray/fetch_object的操作,此处也差不多,该类具体的方法可以参阅下方的参考资料。我常用的两个方法,一个是fetch_hash,另一个是each_hash。前者返回一个hash,和php中的fetch_array是一个效果;后者可以传入一个block,省得写while循环。
res.each_hash{ |h| puts h['id'] }
这样就能得到每一行数据了。最近深刻感觉到,不光是rails,ruby下的每个东西,都是那么精致好用。ruby是慢了点,但在我导入数据的过程中观察日志,花在数据库上的时间超过了90%,所以哪怕用c来写,能提升的也只是那10%的效率,聊胜于无。
后续我会把优化程序、提高导入效率的一些心得写下来。其实在牛人看来,这样的数据并不算多,但还是足够我研究一阵子了。
参考资料:
1、Ruby/Mysql文档
2、脱离rails使用ActiveRecord