批量插入Impala需要花费太多时间

时间:2017-02-01 12:36:22

标签: jdbc prepared-statement cloudera impala

我正在使用Impala JDBC驱动程序将数据批量插入Impala。我目前的批处理大小为1000,并使用PreparedStatement的INSERT INTO VALUES子句来执行批处理查询。 Impala守护程序在3台计算机上运行,​​而Impala目录服务器,状态存储正在第4台计算机上运行。

Impala上的批量插入查询计划如下所示:

Query Timeline: 35s398ms
   - Query submitted: 0.000ns (0.000ns)
   - Planning finished: 34s822ms (34s822ms)
   - Submit for admission: 34s886ms (63.997ms)
   - Completed admission: 34s886ms (0.000ns)
   - Ready to start 1 fragment instances: 34s886ms (0.000ns)
   - All 1 fragment instances started: 34s958ms (71.997ms)
   - DML data written: 35s082ms (123.996ms)
   - DML Metastore update finished: 35s286ms (203.993ms)
   - Request finished: 35s298ms (11.999ms)
   - Unregister query: 35s374ms (75.997ms)
 - ComputeScanRangeAssignmentTimer: 0.000ns

正如我们所看到的,计划完成正在全力以赴。我们尝试过以两种格式创建PARQUET和普通格式。但每次规划完成部分都太高了。

我需要更改配置吗?或者我做错了什么?

3 个答案:

答案 0 :(得分:2)

首先要注意的是,即使您批量使用单个PreparedStatement,每行仍将获得自己的INSERT语句。例如,准备好的声明

INSERT INTO t VALUES (?, ?);

将插入两行

INSERT INTO t VALUES ('a', 1);
INSERT INTO t VALUES ('b', 2);

而不是

INSERT INTO t VALUES ('a', 1), ('b', 2);

接下来要考虑的是,在Hadoop中插入单行效率非常低,因为必须为每一行创建一个新的HDFS文件。

摘自the Impala documentation

  

INSERT ... VALUES技术不适合将大量数据加载到基于HDFS的表中,因为插入操作无法并行化,并且每个都生成一个单独的数据文件。使用它来设置小维度表或少量数据以试验SQL语法或HBase表。不要将它用于大型ETL作业或负载操作的基准测试。不要运行包含数千个INSERT ... VALUES语句的脚本,每次都插入一行。如果您运行INSERT ... VALUES操作以将数据作为ETL管道中的一个阶段加载到临时表中,请在每个VALUES子句中包含多个行值(如果可能),并使用单独的数据库使清理更容易该操作确实产生了许多小文件。

答案 1 :(得分:0)

通过对多行使用一个 insert 语句来加载数据的示例代码:

USE my_schema
;

DROP TABLE IF EXISTS my_countries
;

CREATE TABLE IF NOT EXISTS my_countries (
  country_id int
, country_name string
)
;

INSERT INTO my_countries VALUES
  ( 1, 'UK')
, ( 2, 'USA')
;

答案 2 :(得分:0)

为了更好的性能;

  1. 写入 hdfs
  2. 然后在impala中创建一个临时表作为与该HDFS路由关联的外部表
  3. 从该外部表插入您的表

如果你让 hadoop 集群处理插入而不是你的机器,这将是一个更好的性能。