最近建立数据仓库的过程中遇到了若干问题,现总结如下。
1 mysql到oracle的迁移。这是个复杂的问题,因为我们没有计划投资购买datastage这样牛逼的ETL工具,因此最开始我决定自己写代码,将mysql的数据导入文本中,再利用sqlldr将数据导入到oracle中。这个过程说起来并不是很复杂,但是实际操作起来比较烦,因为我遇到了如下的问题:
1.1 NULL值。mysql导出文件的时候null值会被处理为“\N”,这样在入库的时候oracle会直接将它当做一个字符来处理,因此就出现了这样的困扰,我也许还需要在数据导入成功以后进行一次update操作,四五万条数据我也就认了,可是动辄百万千万的数据,我是没有这个耐心的。于是我选择了在SQL中进行修改,写了case when语句将null处理成了'',这样sqlldr入库的时候就会将它处理成null值了。
1.2 汉字。搞程序的人也许对汉字会又爱又恨,因为我们程序员英语好的不多,大部分人很讨厌读英文文档,一方面又要面对汉字经常乱码的问题。在对mysql的导出数据进行入库的时候就出现了汉字乱码的问题,而且比较奇怪的是,在我直接在数据库服务器上用sqlplus进行查询的时候汉字显示正常,而在远程windows上用plsql dev查,汉字就是一堆乱码了。后来我在控制文件的第二行加了这样一句:“characterset UTF8”,解决了这个问题。希望大家遇到类似的问题能用我的这个方法解决掉。
1.3 换行。业务系统是面向用户的,不能要求用户进行很规范的输入,比如有的用户就喜欢在注册昵称里加很多特殊字符,而我被各种各样的换行符困扰了很久。回车换行是比较常见的换行符,在android这样的操作系统里,换行符属于linux形式,被导出来的时候,mysql并不会将换行符以某种形式导出,而是直接在文本中进行了换行,比如一个人的昵称是
“阳光小男生
我爱XXX”
那么在输出的时候就是这样的(表结构是id, nickname):
123, 阳光小男生
我爱XXX
这样子入库的时候sqlldr就识别不了了,只能按照第二行入库,但是id是number型的,入库的时候“我爱XXX”是会报错的。为了解决这个问题,只好再用case when对“\n”进行处理,处理成'',反正数据仓库并不需要将这些非主流的名字那么精确地入库。接下来还会遇到的就是windows的换行符了,对于这个问题,还是用case when处理,于是有些非主流的信息只能加了好几层case when进行处理。真是让我无力吐槽。
2 工具。对于工具其实ETL界最有名的莫过于datastage了,但是IBM的东西一向很贵,而且部署起来成本也是比较大的。所以互联网公司一般会转向开源软件,这个时候google告诉我有一款叫做kettle的软件很好用。
kettle主要包括了三个部分,spoon,kitchen和pan。都是厨房用具,连kettle都是水壶的意思,外国人有时候确实很有意思。其中spoon是图形化界面,可以用于新建转换和作业这些操作,kitchen用于调度作业,pan用于调度转换。因为kettle并不像DS那样,有服务端和客户端,在客户端建立的Job,服务端会定期调度,如果要kettle实现这一功能,就必须把spoon一直开着,而且把job置为运行状态,这样做很容易导致java heap报错。因此大家都推荐使用crontab定时调度kitchen。
一个多月以来我试验了上述的两种方法,第一种方法是我第一家企业,那个研究所喜欢使用的,但是我通过实际操作发现,自己写代码,维护的成本会很大,而且很容易出错,如果这个人走了,那么接手的人会很难受。而使用工具是业界比较流行的做法,其实用好一款工具,精通它,那么你在这个领域也能称为达人了,现在我才深刻的理解了那句“工欲善其事,必先利其器”。
Kettle的用法,我会慢慢总结。