工具:bcp
测试效率:
新闻数据库,10 000 000行,25.8G
导出时间:约2个小时
每秒约1326行
方法二:
用循环执行sql语句,分段写入文件。
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值插入,而不是这列的默认值。
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优化导致的。但是,考虑到实际需要,如果需对一个文件有控制,则可以自己设定文件大小。
创建符合行列规则的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
多线程每个线程处理一个文件导入到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);
}
}
}