hive 如何处理插入到内部分区 table?

How does hive handle insert into internal partition table?

我需要将记录流插入分区的 Hive table。 table 结构类似于

CREATE TABLE store_transation (
     item_name string,
     item_count int,
     bill_number int,
) PARTITIONED BY (
   yyyy_mm_dd string
);

我想了解 Hive 如何处理内部插入 table。

是否所有记录都插入到单个文件里面 yyyy_mm_dd=2018_08_31目录?或者 hive 在一个分区内拆分成多个文件,如果是什么时候?

如果每天有 100 万条记录并且查询模式将在日期范围之间,那么以下哪个表现较好?

  1. 内部没有分区table
  2. 按日期分区,每个日期只有一个文件
  3. 按日期分区,每个日期有多个文件

Insert 将在所有情况下执行相同的操作,因为 insert 不会查询现有数据(除非您使用 select 从自身插入)并且通常每个容器都会创建自己的文件,除非文件合并是已配置。

如果 table 按日期分区,使用日期范围查询数据会更好。文件太多可能会导致性能下降,因此您可能希望在插入期间合并文件。什么是文件太多?就像每个每日分区数百甚至数千。每个分区的文件很少不会导致性能问题,您不需要合并它们。

Insert 语句将在分区目录中创建附加文件,并且通常不会与现有文件合并。将创建多少文件取决于插入语句和配置设置。

最终映射器或缩减器的数量运行 + 配置设置将决定输出文件的数量。您可以通过例如添加 'order by' 子句在单个减速器上强制它 运行 。在这种情况下,每个分区将创建一个额外的文件,但它会运行缓慢。 distribute by partition key 也可用于减少创建的文件数量,但这会触发额外的 reducer 阶段,并且会比 map-only 任务运行得更慢。

您还可以使用这些设置将新文件与现有文件合并:

SET hive.merge.mapfiles=true;
SET hive.merge.mapredfiles=true;
SET hive.merge.size.per.task=128000000; -- (128MB)
SET hive.merge.smallfiles.avgsize=128000000; -- (128MB)

这些配置设置可能会在最后触发合并任务(取决于上面设置中配置的大小),它会合并现有文件以及插入新添加的文件。

有关合并的更多详细信息,请参阅此答案:

实际上 table 的类型,托管的或外部的,在这种情况下并不重要。 Insert 或 select 的效果相同。

如果您已经有与目标 table 格式相同的文件,那么最快的方法是将它们放在分区目录中,根本不使用 DML 查询。

对于 ORC 文件,您可以使用以下命令有效地合并文件:ALTER TABLE T [PARTITION partition_spec] CONCATENATE;