批量插入 Impala 花费太多时间

Batch Insert into Impala taking too much time

我正在使用 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 和普通格式。但是每次Planning完成的部分都太高了。

我需要做任何配置更改吗?还是我做错了什么?

首先要注意的是,即使您批量使用单个 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

The INSERT ... VALUES technique is not suitable for loading large quantities of data into HDFS-based tables, because the insert operations cannot be parallelized, and each one produces a separate data file. Use it for setting up small dimension tables or tiny amounts of data for experimenting with SQL syntax, or with HBase tables. Do not use it for large ETL jobs or benchmark tests for load operations. Do not run scripts with thousands of INSERT ... VALUES statements that insert a single row each time. If you do run INSERT ... VALUES operations to load data into a staging table as one stage in an ETL pipeline, include multiple row values if possible within each VALUES clause, and use a separate database to make cleanup easier if the operation does produce many tiny files.

通过对多行使用一个 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')
;

为了更好的表现;

  1. 写入 hdfs
  2. 然后在 impala 中创建一个分段 table 作为与该 HDFS 路由关联的外部 table
  3. 从外部 table
  4. 插入你的 table

如果让 hadoop 集群而不是您的机器处理插入,性能会好得多。