【问题标题】:spark ORC fine tuning (file size, stripes)spark ORC 微调(文件大小,条纹)
【发布时间】:2020-02-19 00:05:37
【问题描述】:

我的问题分为两部分:

如何使用 spark 设置(微调)高级 ORC 参数?

各种帖子显示Spark Small ORC StripesHow 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", ...) 二次排序进行了重新分区和排序。排序列的顺序由昂贵(长字符串)列的基数选择。最高的先去。

文件大小

我想将 gzip 压缩的 orc 文件写入 HDFS。 小文件大小问题是我所知道的并且显然想要防止 - 但另一个方向呢? 例如,如果相应地重新分区,我的一个数据集将生成 800MB gzipped orc 文件(分区内的单个文件)。 这些 800MB 是否已经被认为太大了?我应该尝试将这些大小调整为大约 300MB 左右吗?还是400MB?请记住,它们已经被压缩了。

条带大小

目前,我从以下方面观察:

java-jar orc-tools meta foo.orc

对于这个文件之前(以及其他文件)spark 似乎创建了大小约为 16MB 的条纹,即在这种特殊情况下为 49。

这是第一个 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 中使用吗?

其他调优技巧

请与我分享任何其他调整技巧。

【问题讨论】:

    标签: apache-spark hive filesize orc


    【解决方案1】:

    不完整的学习

    问题的相当一部分仍然悬而未决。请改进答案。

    如何在 spark 中设置调优参数

    对于 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,但保持条带大小 在 ¼ 块大小到 4 个块大小之间(默认 ORC 块大小为 256 MB

    这意味着更大的条带更好,但在加载过程中创建更耗时(权衡)。

    兽人好东西

    索引在 Hive 3.0 中从 hives 方面删除,因为它们的功能直接在 ORC 文件中实现(排序时的 min-max 对范围非常有效,bloomfilter 用于等连接条件。 https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Indexing

    另外创建一个bloomfilter 是有意义的,但需要在存储和时间上进行权衡。 创建bloomfilters时,可以使用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/(搜索这些不同的编码)可能有意义。

    spark 建议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
    

    额外的好读物

    什么仍然开放

    • 有关选择正确参数的更多信息
    • 为什么 spark 中的条带大小要小得多(16-20MB 对比推荐的 64MB)?也许我需要尝试调整步幅。
    • 为什么它们会保持这么小(即使尝试增加它们)。请记住:2.2.x、HDP 2.6.4 和原生 ORC 支持应该已经修复。

    • 什么时候使用bloomfilters,这些什么时候过分了?

    https://www.slideshare.net/BenjaminLeonhardi/hive-loading-data

    【讨论】:

      猜你喜欢
      • 2019-02-04
      • 2019-02-11
      • 1970-01-01
      • 2018-10-07
      • 2017-07-23
      • 2020-02-14
      • 2011-10-18
      • 2018-03-02
      • 2015-08-27
      相关资源
      最近更新 更多