我的问题分为两个部分:
各种帖子表明可能存在问题Spark Small ORC Stripes,How to set ORC stripe size in Spark。我目前在HDP 2.6.4平台上使用spark 2.2,因此根据https://community.cloudera.com/t5/Support-Questions/Spark-ORC-Stripe-Size/td-p/189844,这应该已经解决。但是,我不清楚执行时如何设置这些参数:
df.write.orc("/path/to/file")
也许只是一个:
df.write.options(Map("key"-> "value")).orc("/path/to/file")
但是,我也不确定我在这里需要哪些键。
注意:使用的是1.4
native
版本的ORC。.set("spark.sql.orc.impl", "native") .set("spark.sql.hive.convertMetastoreOrc", "true")
我的数据集被重新分区并使用
df.repartition(number, c1,c2,...).sortWithin("c1, c2", "c3", ...)
进行二次排序。排序列的顺序由昂贵(长字符串)列的基数来选择。最高的优先。
我想将压缩的orc文件写入HDFS。 小文件大小问题是我已经知道的,显然是要防止的-但是其他方向呢? 例如,如果相应地重新分区,我的数据集之一将生成800MB压缩的orc文件(分区内的单个文件)。 这些800MB是否已经被认为太大?我是否应该尝试将其大小调整为大约300MB?还是400MB?请记住,它们已经被压缩了。
目前,我从以下位置观察到
:java-jar orc-tools meta foo.orc
在此文件之前(还有其他文件),火花似乎会创建大约16MB的条纹,在这种情况下为49MB。
以下是第一个Stripe输出的示例:
Stripe 1:
Column 0: count: 3845120 hasNull: false
Column 1: count: 3845120 hasNull: false min: a max: b sum: 246087680
Column 2: count: 3845120 hasNull: false min: aa max: bb sum: 30288860
Column 3: count: 3845120 hasNull: false min: aaa max: bbb sum: 89174415
Column 4: count: 3845120 hasNull: false
Column 5: count: 3845120 hasNull: false min: 2019-09-24 00:00:00.0 max: 2019-09-24 23:45:00.0 min UTC: 2019-09-24 02:00:00.0 max UTC: 2019-09-25 01:45:00.0
Column 6: count: 3845120 hasNull: false min: 2019-09-24 00:15:00.0 max: 2019-09-25 00:00:00.0 min UTC: 2019-09-24 02:15:00.0 max UTC: 2019-09-25 02:00:00.0
Column 7: count: 3845120 hasNull: false min: 1 max: 36680 sum: 36262602
在列出所有条纹(再次是第一个条纹)后的详细输出中:
Stripes:
Stripe: offset: 3 data: 17106250 rows: 3845120 tail: 185 index: 51578
Stream: column 0 section ROW_INDEX start: 3 length 55
Stream: column 1 section ROW_INDEX start: 58 length 21324
Stream: column 2 section ROW_INDEX start: 21382 length 3944
Stream: column 3 section ROW_INDEX start: 25326 length 12157
Stream: column 4 section ROW_INDEX start: 37483 length 55
Stream: column 5 section ROW_INDEX start: 37538 length 4581
Stream: column 6 section ROW_INDEX start: 42119 length 4581
Stream: column 7 section ROW_INDEX start: 46700 length 4881
Stream: column 1 section DATA start: 51581 length 57693
Stream: column 1 section LENGTH start: 109274 length 16
Stream: column 1 section DICTIONARY_DATA start: 109290 length 623365
Stream: column 2 section DATA start: 732655 length 447898
Stream: column 2 section LENGTH start: 1180553 length 148
Stream: column 2 section DICTIONARY_DATA start: 1180701 length 968
Stream: column 3 section DATA start: 1181669 length 2449521
Stream: column 3 section LENGTH start: 3631190 length 6138
Stream: column 3 section DICTIONARY_DATA start: 3637328 length 303255
Stream: column 5 section DATA start: 3940583 length 5329298
Stream: column 5 section SECONDARY start: 9269881 length 172
Stream: column 6 section DATA start: 9270053 length 5334123
Stream: column 6 section SECONDARY start: 14604176 length 172
Stream: column 7 section DATA start: 14604348 length 2553483
Encoding column 0: DIRECT
Encoding column 1: DICTIONARY_V2[16914]
Encoding column 2: DICTIONARY_V2[214]
Encoding column 3: DICTIONARY_V2[72863]
Encoding column 4: DIRECT
Encoding column 5: DIRECT_V2
Encoding column 6: DIRECT_V2
Encoding column 7: DIRECT_V2
这里推荐什么? Hive的默认值似乎提到256MB,但这似乎与spark计算的值范围完全不同。这里的理由是什么?
那为什么呢?
spark.conf.get("orc.dictionary.key.threshold")
java.util.NoSuchElementException: orc.dictionary.key.threshold
失败,即使可以清楚地看到以某种方式设置了字典?查看spark的代码库,我无法确定此属性是否在https://github.com/apache/spark/search?q=orc.dictionary.key.threshold&unscoped_q=orc.dictionary.key.threshold
的任何地方设置orc的最新版本引入了布隆过滤器和索引。这些也可以用于spark吗?
请与我分享其他调优技巧。
答案 0 :(得分:1)
问题的某些部分仍未解决。请改进答案。
对于ORC高级设置:
https://spark.apache.org/docs/latest/sql-data-sources-load-save-functions.html
usersDF.write.format("orc") .option("orc.bloom.filter.columns", "favorite_color") .option("orc.dictionary.key.threshold", "1.0") .save("users_with_options.orc")
实际上,可以将它们简单地作为.option
传递给writer
。
如果您想在使用--conf
来启动Spark时进行设置,请确保为它们加上spark.orc.bloom.filter.columns
作为前缀,否则将被忽略。
选择正确的文件大小很重要。越大往往越好。实际上,我可以观察到5个文件与10个文件在1GB左右的差异(5个文件的存储需求较少)。
https://community.cloudera.com/t5/Community-Articles/ORC-Creation-Best-Practices/ta-p/248963 ORC文件可在条带级别上可拆分。条纹尺寸为 可配置,应取决于记录的平均长度(大小)和 您可以拥有这些排序字段的多少个唯一值。如果 搜索字段是唯一的(或几乎是唯一的),请减小条带大小 大量重复-增加。当默认值为64 MB时,保持条带大小 在1/4块大小到4块大小之间(默认ORC块大小为 256 MB
这意味着较大的条纹更好,但在加载过程(折衷)中创建起来要花费更多时间。
索引在Hive 3.0中从配置单元中删除,因为它们的功能直接在ORC文件中实现(排序时的min-max对范围非常有效,bloomfilter对于等联接条件。 https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Indexing
另外创建bloomfilter是有意义的,但是在存储和时间上需要权衡。
创建Bloomfilter后,可以使用orce-tools
Stripes:
Stripe: offset: 3 data: 20833464 rows: 3475000 tail: 256 index: 3981255
Stream: column 0 section ROW_INDEX start: 3 length 52
Stream: column 0 section BLOOM_FILTER start: 55 length 17940
Stream: column 1 section ROW_INDEX start: 17995 length 31010
Stream: column 1 section BLOOM_FILTER start: 49005 length 610564
Stream: column 2 section ROW_INDEX start: 659569 length 4085
Stream: column 2 section BLOOM_FILTER start: 663654 length 378695
Stream: column 3 section ROW_INDEX start: 1042349 length 11183
Stream: column 3 section BLOOM_FILTER start: 1053532 length 1936342
排序是至关重要的(https://community.cloudera.com/t5/Community-Articles/ORC-Creation-Best-Practices/ta-p/248963),应作为次要排序(已在问题中概述)。
看起来很有用,不需要超级耗时的微调:
orc.dictionary.key.threshold=0.95 # force dict (almost) always (seems useful for almost all (non streaming) use cases)
orc.bloom.filter.columns "*" # do not use star, but select desired columns to save space
另外,orc.column.encoding.direct https://orc.apache.org/specification/ORCv1/(搜索这些不同的编码)可能很有意义。
火花建议https://spark.apache.org/docs/latest/cloud-integration.html:
spark.sql.orc.filterPushdown true
spark.sql.orc.splits.include.file.footer true
spark.sql.orc.cache.stripe.details.size 10000
spark.sql.hive.metastorePartitionPruning true
为什么它们会保持这么小(即使试图增大它们)。请记住:2.2.x,HDP 2.6.4和本机ORC支持应该已经修复。
什么时候使用Bloomfilters,这些什么时候过大?
https://www.slideshare.net/BenjaminLeonhardi/hive-loading-data