方法一:
环境: win7+sqlserver2008
工具: bcp
测试效率:
新闻数据库, 10 000 000 行, 25.8G
导出时间:约 2 个小时
每秒约 1326 行
方法二:
用循环执行sql语句,分段写入文件。
1 Bcp 介绍
bcp 实用工具可以在 Microsoft SQL Server 实例和用户指定格式的数据文件间大容量复制数据。 使用 bcp 实用工具可以将大量新行导入 SQL Server 表,或将表数据导出到数据文件。 除非与 queryout 选项一起使用,否则使用该实用工具不需要了解 Transact-SQL 知识。 若要将数据导入表中,必须使用为该表创建的格式文件,或者必须了解表的结构以及对于该表中的列有效的数据类型。
(1) 导入。
这个动作使用 in 命令完成,后面跟需要导入的文件名。
(2) 导出。
这个动作使用 out 命令完成,后面跟需要导出的文件名。
(3) 使用 SQL 语句导出。
这个动作使用 queryout 命令完成,它跟 out 类似,只是数据源不是表或视图名,而是 SQL 语句。
(4) 导出格式文件。
这个动作使用 format 命令完成,后而跟格式文件名。
下面介绍一些常用的选项:
-f format_file
format_file 表示格式文件名。这个选项依赖于上述的动作,如果使用的是 in 或 out , format_file 表示已经存在的格式文件,如果使用的是 format 则表示是要生成的格式文件。
-x
这个选项要和 -f format_file 配合使用,以便生成 xml 格式的格式文件。
-F first_row
指定从被导出表的哪一行导出,或从被导入文件的哪一行导入。
-L last_row
指定被导出表要导到哪一行结束,或从被导入文件导数据时,导到哪一行结束。
-c
使用 char 类型做为存储类型,没有前缀且以 "\t" 做为字段分割符,以 "\n" 做为行分割符。
-w
和 -c 类似,只是当使用 Unicode 字符集拷贝数据时使用,且以 nchar 做为存储类型。
-t field_term
指定字符分割符,默认是 "\t" 。
-r row_term
指定行分割符,默认是 "\n" 。
-S server_name[ \instance_name]
指定要连接的 SQL Server 服务器的实例,如果未指定此选项, bcp 连接本机的 SQL Server 默认实例。如果要连接某台机器上的默认实例,只需要指定机器名即可。
-U login_id
指定连接 SQL Sever 的用户名。
-P password
指定连接 SQL Server 的用户名密码。
-T
指定 bcp 使用信任连接登录 SQL Server 。如果未指定 -T ,必须指定 -U 和 -P 。
-k
指定空列使用 null 值插入,而不是这列的默认值。
2 部署与流程
3 详细设计
3.1 Sqlserver 数据导出到临时文本阶段
Log 类
BcpSqlserver 类
JdbcStream 类
SqlserverToTxt 类
(代码见 SVN-SqlserverToHive )
此阶段的是根据自定义每个导出文件中的数据行数进行分文件导出,一个导出成果如下:
导出效率分析:
测试一个文件 1000,10000,100000 条数据,比较完成时间:
文件数据行数 = 1000 start:1359102390172 end:1359102452310 time use :62138ms
文件数据行数 = 10000 start:1359102452310 end:1359102461626 time use :9316ms
文件数据行数 = 100000 start:1359102461626 end:1359102462997 time use :1371ms
文件数据行数 = 1000000 start:1359102577696 end:1359102578501 time use :805ms
所以,用 bcp 导数据,文件越少效率越高,这是 bcp 内部的 sql 优化导致的。但是,考虑到实际需要,如果需对一个文件有控制,则可以自己设定文件大小。
3.2 临时文本导入到 hive/hdfs 阶段
3.2.1 导入 hive
创建符合行列规则的 hive 表
CREATE TABLE table1 (a STRING, b STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' ESCAPED BY '\\'
STORED AS TEXTFILE;
Jdbc 连接 hive ,执行 load 语句
LOAD DATA LOCAL INPATH '/home/admin/test/test.txt' OVERWRITE INTO TABLE test_1
或者直接创建外表指向hdfs中的数据文件
create external table IF NOT EXISTS mytest (ID string,Symbol string) LOCATION '/tmp/sqltohdfs
3.2.2 导入 hdfs
多线程每个线程处理一个文件导入到 hdfs 中
参考代码
import java.io.IOException;
import java.net.URI;
import java.io.FileInputStream;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
public class LocalToHDFS {
// s 为本地文件路径
// d 为 hdfs 绝对路径
public static void uploadLocalFile2HDFS (String s, String d)
throws IOException {
Configuration conf = new Configuration();
FileSystem hdfs = FileSystem. get (URI. create (d), conf);
FileInputStream in = null ;
FSDataOutputStream out = null ;
try {
in = new FileInputStream(s);
out = hdfs.create( new Path(d));
IOUtils. copyBytes (in, out, 4096, false );
} finally {
IOUtils. closeStream (in);
IOUtils. closeStream (out);
}
}
}