问题描述

现有几千条数据,需要插入到对应的Hive/Impala表中。安排给了一个同事做,但是等了好久,反馈还没有插入完成……看到他的做法是:对每条数据进行处理转换为对应的insert语句,但是,实际执行起来,速度很慢,每条数据都要耗时1s左右。比在MySQL中批量插入数据慢多了,因而抱怨Impala不太好用

问题分析

首先,必须明确的是,把每条数据处理成insert语句的方式,肯定是最低效的,不管是在MySQL中,还是在分布式组件Hive、Impala中。

这种方式的资源消耗,更多的花在了连接、SQL语句的解析、执行计划生成上,实际插入数据的开销还是相对较少的。

所以,要提高批量数据的插入,关键是减少无谓的资源开销,提高一条SQL的吞吐率,即通过尽量少的SQL条数,插入更多的数据。

解决方案

测试数据:

aaa
bbb
ccc
ddd
eee
fff
ggg
hhh
iii
jjj

测试表:

create table if not exists test.test_batch_insert(
f1 string
) comment 'test for batch insert'
row format delimited fields terminated by '\t' lines terminated by '\n'
stored as textfile;

方案1(最慢的):数据转换为insert语句

step1:处理成sql语句

vim中:
%s/^/insert into test.test_batch_insert select '/g
%s/$/';/g 或者使用awk:
awk '{printf "insert into test.test_batch_insert select \"%s\";\n", $0}' test.txt > test.sql

生成的SQL脚本:

insert into test.test_batch_insert select "aaa";
insert into test.test_batch_insert select "bbb";
insert into test.test_batch_insert select "ccc";
insert into test.test_batch_insert select "ddd";
insert into test.test_batch_insert select "eee";
insert into test.test_batch_insert select "fff";
insert into test.test_batch_insert select "ggg";
insert into test.test_batch_insert select "hhh";
insert into test.test_batch_insert select "iii";
insert into test.test_batch_insert select "jjj";

step2:执行生成的SQL脚本

impala-shell -i data1 -f test.sql

一条条执行,比较慢……

方案2(相对快点):一条SQL尽量插入多条数据

step1:转换成SQL

awk 'BEGIN{print "insert into test.test_batch_insert"; i=1; n=10} {if(i<n){ printf "select \"%s\" union\n", $0; i++} else {printf "select \"%s\";", $0}}' test.txt > test2.sql

vim %s 或者 sed也行

生成的SQL脚本:

insert into test.test_batch_insert
select "aaa" union
select "bbb" union
select "ccc" union
select "ddd" union
select "eee" union
select "fff" union
select "ggg" union
select "hhh" union
select "iii" union
select "jjj";

step2:执行生成的SQL

执行前,先清空表;

impala-shell -i data1 -f test2.sql

执行之后,会发现,不止快了一点点……

但是,这种方式有局限……

因为,一条SQL的长度是有限制的,数据量大了,只生成一条SQL,会导致超长,无法执行。此时,可以考虑分割文件:

split -l 500 test.txt test_split_

然后,编写脚本遍历每个文件分片,重复上述操作即可。

方案3(最快的,如果你没有更好的)

step1:首先查看下test.test_batch_insert的建表语句:

impala-shell -i data1 -B -q "show create table test.test_batch_insert"

建表语句如下:

Query: show create table test.test_batch_insert
"CREATE TABLE test.test_batch_insert (
f1 STRING
)
COMMENT 'test for batch insert'
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'
WITH SERDEPROPERTIES ('field.delim'='\t', 'line.delim'='\n', 'serialization.format'='\t')
STORED AS TEXTFILE
LOCATION 'hdfs://xxxxxx:8020/user/hive/warehouse/test.db/test_batch_insert'
"

关注一下LOCATION属性,在HDFS上查看下该路径:

hdfs dfs -ls /user/hive/warehouse/test.db/test_batch_insert

然后,看下文件内容:

hdfs dfs -cat /user/hive/warehouse/test.db/test_batch_insert/*data.0.

发现了吧,就是可读的纯文本文件,每行都是一条数据。因为前面建表的时候,就指定了用\n作为记录分隔符。

看到这里,聪明的你,应该知道我接下来要做什么了……

step2:上传数据文件

首先,再次清空test.test_batch_insert;

然后,上传文件:

hdfs dfs -put test.txt /user/hive/warehouse/test.db/test_batch_insert

此时,在hive表中,应该能直接查询到数据了,impala中还需要刷新下表:

impala-shell命令行窗口中执行:
refresh test.test_batch_insert;

然后,搞定了……

其实,hive/impla类似于MySQL,有对应的load data的语句……这里只是把load data语句实际干的事展示了一下……

Hive/Impala批量插入数据的更多相关文章

  1. C#批量插入数据到Sqlserver中的四种方式

    我的新书ASP.NET MVC企业级实战预计明年2月份出版,感谢大家关注! 本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的 ...

  2. .Net批量插入数据到SQLServer数据库,System.Data.SqlClient.SqlBulkCopy类批量插入大数据到数据库

    批量的的数据导入数据库中,尽量少的访问数据库,高性能的对数据库进行存储. 采用SqlBulkCopy来处理存储数据.SqlBulkCopy存储大批量的数据非常的高效,将内存中的数据表直接的一次性的存储 ...

  3. sql 中的Bulk和C# 中的SqlBulkCopy批量插入数据 ( 回顾 and 粗谈 )

    通常,我们会对于一个文本文件数据导入到数据库中,不多说,上代码. 首先,表结构如下.   其次,在我当前D盘中有个文本文件名为2.txt的文件. 在数据库中,可以这样通过一句代码插入. Bulk in ...

  4. Java 批量插入数据(Oracle)

    //批量添加20000条数据用时8秒. try {    String url = "jdbc:oracle:thin:@IP:1521:orcl"; // orcl为数据库的SI ...

  5. 批量插入数据(基于Mybatis的实现-Oracle)

    前言:做一个数据同步项目,要求:同步数据不丢失的情况下,提高插入性能. 项目DB框架:Mybatis.DataBase:Oracle. -------------------------------- ...

  6. C#批量插入数据到Sqlserver中的三种方式

    本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生 成 ...

  7. SqlServer——批量插入数据

    像Major表里面批量插入数据演示: 代码如下: Declare @I int Set @I= Begin Tran InsertData: Insert into Major values(@I,' ...

  8. mybatis批量插入数据到oracle

    mybatis 批量插入数据到oracle报 ”java.sql.SQLException: ORA-00933: SQL 命令未正确结束“  错误解决方法 oracle批量插入使用 insert a ...

  9. SQLServer 批量插入数据的两种方法

    SQLServer 批量插入数据的两种方法-发布:dxy 字体:[增加 减小] 类型:转载 在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Ins ...

随机推荐

  1. java基础-内存分配

    1.java运行时的数据区:程序计数器.方法区.虚拟机栈.本地方法栈.堆 ①.程序计数器:一块较小的内存空间,可看作当前线程所执行的字节码的行号指示器 ②.java虚拟机栈:与程序计数器一样,也是线程 ...

  2. oracle函数 INSTRB(C1,C2[,I[,J]])

    [功能]在一个字符串中搜索指定的字符,返回发现指定的字符的位置; [说明]多字节符(汉字.全角符等),按2个字符计算 [参数] C1    被搜索的字符串 C2    希望搜索的字符串 I     搜 ...

  3. Android Animation动画实战(二):从屏幕底部弹出PopupWindow

    在这篇文章之前,我已经陆陆续续写了几篇博客,介绍了Android Animation是如何使用的,有还不明白的,可以点击查看: 1. Android Animation动画详解(一): 补间动画 2. ...

  4. SQL server无法绑定由多个部分绑定的标示符

    原因https://blog.csdn.net/wolfalcon/article/details/54578215给了我启发,原来有犯错在insert和update的使用上了对于已存在的表(表中有字 ...

  5. 最短路径Dijkstra算法和Floyd算法整理、

    转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径—Dijkstra算法和Floyd算法 Dijks ...

  6. Vue 列表动画实现

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. Codeforces Round #196 (Div. 1 + Div. 2)

    A. Puzzles 对\(f[]\)排序,取连续的\(m\)个. B. Routine Problem 考虑\(\frac{a}{b}\)和\(\frac{c}{d}\)的大小关系,适配后就是分数的 ...

  8. Python--day32--复习:https和http的区别;黏包;黏包问题的解决方式;

    1,https和http的区别: https比较安全,传输的时候先对内容进行加密,收到后再进行解密:它的传输内容不容易拦截,就算拦截下来了,也是加密的,看不懂.但是要买证书,一年要好几万,小公司承担不 ...

  9. H3C 各类路由默认优先级

  10. Jenkins 配置自动合并 release 分支到 master 分支

    本文告诉大家如何在 Jenkins 配置合并到 release 的内容自动合并到 gitlab 的 master 分支 首先需要两个仓库,一个是 gitlab 的仓库,另一个是 Jenkins 的仓库 ...