Hive/Impala批量插入数据

问题描述

现有几千条数据,需要插入到对应的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语句实际干的事展示了一下……

原文地址:https://www.cnblogs.com/dqrcsc/p/12154718.html

时间: 2024-08-06 14:05:15

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

向mysql中批量插入数据的性能分析

MYSQL批量插入数据库实现语句性能分析 假定我们的表结构如下 代码如下   CREATE TABLE example (example_id INT NOT NULL,name VARCHAR( 50 ) NOT NULL,value VARCHAR( 50 ) NOT NULL,other_value VARCHAR( 50 ) NOT NULL) 通常情况下单条插入的sql语句我们会这么写: 代码如下   INSERT INTO example(example_id, name, valu

用python操作mysql数据库(之批量插入数据)

#!/usr/bin/env python # -*- coding: utf-8 -*- import MySQLdb #建立连接 conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1qaz#EDC',db='test_db') cur = conn.cursor() #对数据进行操作 li = [('tanzhenx','shaoguan'),('huangmengdie','shaoguan')] #定义一个列表,列表中

SQL Server 批量插入数据的两种方法

在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Insert不仅效率低,而且会导致SQL一系统性能问题.下面介绍SQL Server支持的两种批量数据插入方法:Bulk和表值参数(Table-Valued Parameters). 运行下面的脚本,建立测试数据库和表值参数. [c-sharp] view plaincopy --Create DataBase create database BulkTestDB; go use BulkTes

.Net批量插入数据到SQLServer数据库,SqlBulkCopy类批量插入大数据到数据库

批量的的数据导入数据库中,尽量少的访问数据库,高性能的对数据库进行存储. 采用SqlBulkCopy来处理存储数据.SqlBulkCopy存储大批量的数据非常的高效,将内存中的数据表直接的一次性的存储到数据库中,而不需要一次一次的向数据库Insert数据. 经过几次实验,百万级别的数据表,也只需几秒时间内就可以完全的存入数据库中,其速度,比传统的Insert into方法不止快很多倍. 下面看代码: /// <summary> /// 批量插入数据 /// </summary> /

Android批量插入数据到SQLite数据库

Android中在sqlite插入数据的时候默认一条语句就是一个事务,因此如果存在上万条数据插入的话,那就需要执行上万次插入操作,操作速度可想而知.因此在Android中插入数据时,使用批量插入的方式可以大大提高插入速度. 有时需要把一些数据内置到应用中,常用的有以下2种方式:其一直接拷贝制作好的SQLite数据库文件,其二是使用系统提供的数据库,然后把数据批量插入.我更倾向于使用第二种方式:使用系统创建的数据库,然后批量插入数据.批量插入数据也有很多方法,那么那种方法更快呢,下面通过一个dem

用SqlBulkCopy批量插入数据到SqlServer数据库表中

首先创建一个数据库连接类:SQLHelper using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.SqlClient; using System.Data; namespace insetData { public class SQLHelper { public static readonly string Strconn = "Data

有关批量插入数据的问题

使用c#批量插入数据时,通过for循环,每次执行一条SQL语句进行数据插入,会使插入操作效率非常低下. 提高效率的方法: 1.SqlBulkCopy类. 2.表值参数. 在SqlServer存储过程中还可以 3.将For循环Insert部分放入一个Transaction中. 具体论证与实现,改日追加. 有关批量插入数据的问题,布布扣,bubuko.com

sql - 批量插入数据

直接构造 insert into t (c1, c2, c3) values (1, 1, 1), (2, 2, 2) 使用UNION insert into t (c1, c2, c3) (select a1, a2, a3) union all (select b1, b2, b3) 利用查询结果 insert into t (c1, c2, c3) (select a1, a2, a3 from t2) sql - 批量插入数据,布布扣,bubuko.com

postgres 使用存储过程批量插入数据

参考资料(pl/pgsql 官方文档): http://www.postgresql.org/docs/9.3/static/plpgsql.html create or replace function creatData2() returns boolean AS $BODY$ declare ii integer; begin II:=1; FOR ii IN 1..10000000 LOOP INSERT INTO ipm_model_history_data (res_model, r