4

我在确保使用 Hive 表中的排序数据时遇到了一些困难。(使用 ORC 文件格式)

DISTRIBUTE BY我知道我们可以通过在 create DDL 中声明一个子句来影响从 Hive 表中读取数据的方式。

CREATE TABLE trades
(
    trade_id INT,
    name STRING,
    contract_type STRING,
    ts INT
)
PARTITIONED BY (dt STRING)
CLUSTERED BY (trade_id) SORTED BY (trade_id, time) INTO 8 BUCKETS
STORED AS ORC;

这意味着每次我对该表进行查询时,数据将trade_id在各个映射器之间分发,然后对其进行排序。

我的问题是:

我不希望将数据拆分为N文件(存储桶),因为体积不大,我会保留小文件。

但是,我确实想利用排序插入。

INSERT OVERWRITE TABLE trades
PARTITION (dt)
SELECT trade_id, name, contract_type, ts, dt
FROM raw_trades
DISTRIBUTE BY trade_id
SORT BY trade_id;

我真的需要CLUSTERED/SORT在创建 DLL 语句中使用吗?或者 Hive/ORC 是否知道如何利用插入过程已经确保数据已排序的事实?

做类似的事情是否有意义:

CLUSTERED BY (trade_id) SORTED BY (trade_id, time) INTO 1 BUCKETS
4

1 回答 1

4

Bucketed table 是一个过时的概念。

您不需要在表 DDL 中写入 CLUSTERED BY。

加载表时使用distribute by partition key减少reducer的压力,特别是在编写ORC时,需要中间缓冲区来构建ORC,如果每个reducer加载许多分区,可能会导致OOM异常。

当表很大时,您可以使用 bytes.per.reducer 限制最大文件大小,如下所示:

set hive.exec.reducers.bytes.per.reducer=67108864;--or even less

如果你有更多的数据,就会启动更多的 reducer,创建更多的文件。这比加载固定数量的桶更灵活。

这也会更好地工作,因为对于小型表,您不需要创建更小的存储桶。

ORC 有内部索引和布隆过滤器。应用 SORT 可以提高索引和布隆过滤器的效率,因为所有相似的数据都将存储在一起。这也可以根据您的数据熵改善压缩。

如果分区键分布不够,因为你有一些数据倾斜并且数据很大,你可以额外随机分布。如果数据分布均匀,最好按列分布。如果没有,请随机分配以避免单个长时间运行的减速器问题。

最后你的插入语句可能看起来像这样:

set hive.exec.reducers.bytes.per.reducer=33554432; --32Mb per reducer

INSERT OVERWRITE TABLE trades PARTITION (dt)
SELECT trade_id, name, contract_type, ts, dt
FROM raw_trades
DISTRIBUTE BY dt,                    --partition key is a must for big data
              trade_id,              --some other key if the data is too big and key is
                                     --evenly distributed (no skew)   
              FLOOR(RAND()*100.0)%20 --random to distribute additionally on 20 equal parts 

SORT BY contract_type; --sort data if you want filtering by this key 
                       --to work better using internal index

不要在表 DDL 中使用 CLUSTERED BY,因为在插入期间使用 DISTRIBUTE BY、ORC w 索引和布隆过滤器 + SORT 可以更灵活地实现相同的目的。

分发+排序可以将ORC文件的大小极大地减少x3或x4倍。类似的数据可以更好地压缩,并使内部索引更高效。

另请阅读:https ://stackoverflow.com/a/55375261/2700344 这是关于排序的相关答案:https ://stackoverflow.com/a/47416027/2700344

您可以在表 DDL 中使用 CLUSTER BY 的唯一情况是,当您加入两个可以由完全相同数量的桶存储的大表时,才能使用 sort-merge-bucket-map-join,但实际上是这样当您可以以相同的方式存储两个大表时,这种情况很少见。只有 1 个桶是没有意义的,因为对于小表,您可以使用 map-join,只需在插入期间对数据进行排序以减少压缩数据的大小。

于 2019-06-10T13:45:51.550 回答