我在确保利用Hive表中的排序数据方面遇到一些困难。 (使用ORC文件格式)
我了解我们可以通过在创建DDL中声明一个DISTRIBUTE BY
子句来影响如何从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;
我真的需要在创建DLL语句中使用CLUSTERED/SORT
吗?还是Hive / ORC知道如何利用插入过程已经确保对数据进行排序这一事实?
做类似的事情是否有意义:
CLUSTERED BY (trade_id) SORTED BY (trade_id, time) INTO 1 BUCKETS
答案 0 :(得分:2)
带桶装桌子是一个过时的概念。
您不需要在表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,创建更多文件。这比加载固定数量的桶更灵活。
这也将更好,因为对于小型表,您不需要创建较小的存储桶。
如果由于分区数据偏斜并且数据量大而无法通过分区键进行分发,则可以另外随机分发。如果您具有均匀分布的数据,则最好按列进行分布。如果不是,请随机分配以避免单个长期运行的减速器问题。
最后,您的插入语句可能看起来像这样:
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索引和Bloom Bloom + SORT可以更灵活地实现相同目的。
另请阅读:https://stackoverflow.com/a/55375261/2700344 这是有关排序的相关答案:https://stackoverflow.com/a/47416027/2700344