在 Hive 中排序 Table(ORC 文件格式)
Sorted Table in Hive (ORC file format)
我在确保在 Hive table 中利用排序数据时遇到了一些困难。 (使用 ORC 文件格式)
我知道我们可以通过在创建 DDL 中声明 DISTRIBUTE BY
子句来影响从 Hive table 读取数据的方式。
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;
这意味着每次我对此 table 进行查询时,数据将通过 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
分桶 table 是一个过时的概念。
您不需要在 table DDL 中编写 CLUSTERED BY。
加载table时使用distribute by partition key
减轻reducer的压力,尤其是在编写ORC时,需要中间缓冲区来构建ORC,如果每个reducer加载很多分区,可能会导致OOM异常。
当 table 较大时,您可以使用 bytes.per.reducer 限制最大文件大小,如下所示:
set hive.exec.reducers.bytes.per.reducer=67108864;--or even less
如果你有更多的数据,就会启动更多的reducer,创建更多的文件。这比加载固定数量的桶更灵活。
这也会更好地工作,因为对于小的 table,您不需要创建更小的桶。
如果由于数据倾斜且数据量大,分区键分配不够,您可以另外进行随机分配。如果数据分布均匀,最好按列分布。如果不是,则随机分配以避免单个 long 运行 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
不要在 table DDL 中使用 CLUSTERED BY,因为在插入期间使用 DISTRIBUTE BY、ORC w 索引和布隆过滤器 + SORT 可以以更灵活的方式实现相同目的。
分发+排序可以将ORC文件的大小极大地减少x3或x4倍。相似的数据可以更好的压缩,让内部索引更有效率。
另请阅读:
这是关于排序的相关答案:
您可以在 table DDL 中使用 CLUSTER BY 的唯一情况是当您加入两个大的 tables 时,它们可以被完全相同数量的桶进行桶装,以便能够使用 sort-merge-bucket-map-join,但实际上,您可以用相同的方式存储两个大 table 的情况非常罕见。只有 1 个桶没有意义,因为对于小的 table,您可以使用 map-join,只需在插入期间对数据进行排序以减少压缩数据大小。
我在确保在 Hive table 中利用排序数据时遇到了一些困难。 (使用 ORC 文件格式)
我知道我们可以通过在创建 DDL 中声明 DISTRIBUTE BY
子句来影响从 Hive table 读取数据的方式。
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;
这意味着每次我对此 table 进行查询时,数据将通过 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
分桶 table 是一个过时的概念。
您不需要在 table DDL 中编写 CLUSTERED BY。
加载table时使用distribute by partition key
减轻reducer的压力,尤其是在编写ORC时,需要中间缓冲区来构建ORC,如果每个reducer加载很多分区,可能会导致OOM异常。
当 table 较大时,您可以使用 bytes.per.reducer 限制最大文件大小,如下所示:
set hive.exec.reducers.bytes.per.reducer=67108864;--or even less
如果你有更多的数据,就会启动更多的reducer,创建更多的文件。这比加载固定数量的桶更灵活。
这也会更好地工作,因为对于小的 table,您不需要创建更小的桶。
如果由于数据倾斜且数据量大,分区键分配不够,您可以另外进行随机分配。如果数据分布均匀,最好按列分布。如果不是,则随机分配以避免单个 long 运行 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
不要在 table DDL 中使用 CLUSTERED BY,因为在插入期间使用 DISTRIBUTE BY、ORC w 索引和布隆过滤器 + SORT 可以以更灵活的方式实现相同目的。
分发+排序可以将ORC文件的大小极大地减少x3或x4倍。相似的数据可以更好的压缩,让内部索引更有效率。
另请阅读:
您可以在 table DDL 中使用 CLUSTER BY 的唯一情况是当您加入两个大的 tables 时,它们可以被完全相同数量的桶进行桶装,以便能够使用 sort-merge-bucket-map-join,但实际上,您可以用相同的方式存储两个大 table 的情况非常罕见。只有 1 个桶没有意义,因为对于小的 table,您可以使用 map-join,只需在插入期间对数据进行排序以减少压缩数据大小。