我在确保利用配置单元表中的排序数据方面遇到了一些困难。(使用ORC文件格式(
我知道我们可以通过在createDDL中声明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
文件(bucket(,因为卷没有那么多,我会保留小文件。
但是,我确实想利用排序插入。
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;
我真的需要在createDLL语句中使用CLUSTERED/SORT
吗?或者Hive/ORC知道如何利用插入过程已经确保数据排序的事实吗?
这样做有意义吗:
CLUSTERED BY (trade_id) SORTED BY (trade_id, time) INTO 1 BUCKETS
带桶表是一个过时的概念。
您不需要在DDL表中写入CLUSTERED BY。
当加载表时,使用distribute by partition key
来降低减压器上的压力,尤其是在编写ORC时,这需要中间缓冲区来构建ORC,如果每个减压器加载多个分区,则可能会导致OOM异常。
当表很大时,可以使用bytes.per.reducer来限制最大文件大小,如下所示:
set hive.exec.reducers.bytes.per.reducer=67108864;--or even less
如果您有更多的数据,将启动更多的减速器,创建更多的文件。这比装载固定数量的铲斗更灵活。
这也会更好地工作,因为对于小表,您不需要创建更小的bucket。
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索引和bloom filters+SORT可以以更灵活的方式实现同样的目的。
Distribute+sort可以将ORC文件的大小极大地减少x3或x4倍。类似的数据可以更好地压缩,并提高内部索引的效率。
另请阅读以下内容:https://stackoverflow.com/a/55375261/2700344这是关于排序的相关答案:https://stackoverflow.com/a/47416027/2700344
当您可以在表DDL中使用CLUSTER BY时,唯一的情况是当您连接两个大表时,这两个表可以由完全相同数量的桶进行桶化,以便能够使用排序合并桶映射连接,但实际上,当您可以以相同的方式对两个大表格进行桶化时,这种情况非常罕见。只有1个bucket是没有意义的,因为对于小表,您可以使用映射联接,只需在插入期间对数据进行排序即可减少压缩数据的大小。