【问题标题】:Why is dictionary page offset 0 for `plain_dictionary` encoding?为什么`plain_dictionary`编码的字典页面偏移量为0?
【发布时间】:2019-08-09 01:00:59
【问题描述】:

parquet 由 Spark v2.4 Parquet-mr v1.10 生成

n = 10000
x = [1.0, 2.0, 3.0, 4.0, 5.0, 5.0, None] * n
y = [u'é', u'é', u'é', u'é', u'a', None, u'a'] * n

z = np.random.rand(len(x)).tolist()
dfs = spark.createDataFrame(zip(x, y, z), schema=StructType([StructField('x', DoubleType(),True),StructField('y', StringType(), True),StructField('z', DoubleType(), False)]))
dfs.repartition(1).write.mode('overwrite').parquet('test_spark.parquet')

使用parquet-tools v1.12 进行检查

row group 0 
--------------------------------------------------------------------------------
x:  DOUBLE SNAPPY DO:0 FPO:4 SZ:1632/31635/19.38 VC:70000 ENC:RLE,BIT_PACKED,PLAIN_DICTIONARY ST:[min: 1.0, max: 5.0, num_nulls: 10000]
y:  BINARY SNAPPY DO:0 FPO:1636 SZ:864/16573/19.18 VC:70000 ENC:RLE,BIT_PACKED,PLAIN_DICTIONARY ST:[min: a, max: é, num_nulls: 10000]
z:  DOUBLE SNAPPY DO:0 FPO:2500 SZ:560097/560067/1.00 VC:70000 ENC:PLAIN,BIT_PACKED ST:[min: 2.0828331581679294E-7, max: 0.9999892375625329, num_nulls: 0]

    x TV=70000 RL=0 DL=1 DS: 5 DE:PLAIN_DICTIONARY
    ----------------------------------------------------------------------------
    page 0:                   DLE:RLE RLE:BIT_PACKED VLE:PLAIN_DICTIONARY ST:[min: 1.0, max: 5.0, num_nulls: 10000] SZ:31514 VC:70000

    y TV=70000 RL=0 DL=1 DS: 2 DE:PLAIN_DICTIONARY
    ----------------------------------------------------------------------------
    page 0:                   DLE:RLE RLE:BIT_PACKED VLE:PLAIN_DICTIONARY ST:[min: a, max: é, num_nulls: 10000] SZ:16514 VC:70000

    z TV=70000 RL=0 DL=0
    ----------------------------------------------------------------------------
    page 0:                   DLE:BIT_PACKED RLE:BIT_PACKED VLE:PLAIN ST:[min: 2.0828331581679294E-7, max: 0.9999892375625329, num_nulls: 0] SZ:560000 VC:70000

问题:

FPO(第一个数据页偏移)应该总是大于还是小于 DO(字典页偏移)?我从某处读到字典页存储在数据页之后。

对于x & y 列,plain_dictionary 用于编码。但是,为什么两列的字典偏移量都是 0?

如果我使用使用 parquet-cpp v1.5.1 的 pyarrow v0.11.1 检查,它会告诉我has_dictionary_page: False & dictionary_page_offset: None

它有没有字典页面?

【问题讨论】:

    标签: parquet arrows pyarrow parquet-mr


    【解决方案1】:

    第一个数据页的偏移量总是大于字典的偏移量。换句话说,字典首先出现,然后才是数据页。有两个元数据字段用于存储这些偏移量:dictionary_page_offset(又名 DO)和data_page_offset(又名 FPO)。 不幸的是,parquet-mr 没有正确填写这些元数据字段。

    例如,如果字典从偏移量 1000 开始,第一个数据页从偏移量 2000 开始,那么正确的值应该是:

    • dictionary_page_offset = 1000
    • data_page_offset = 2000

    相反,parquet-mr 商店

    • dictionary_page_offset = 0
    • data_page_offset = 1000

    应用于您的示例,这意味着尽管 parquet-tools 显示 DO: 0,但 x 和 y 列仍然是字典编码的(z 列不是)。

    值得一提的是,Impala 正确地遵循了规范,所以你不能依赖每个文件都有这个缺陷。

    parquet-mr 在阅读过程中是这样处理这种情况的:

    // TODO: this should use getDictionaryPageOffset() but it isn't reliable.
    if (f.getPos() != meta.getStartingPos()) {
      f.seek(meta.getStartingPos());
    }
    

    其中getStartingPos 定义为:

    /**
     * @return the offset of the first byte in the chunk
     */
    public long getStartingPos() {
      long dictionaryPageOffset = getDictionaryPageOffset();
      long firstDataPageOffset = getFirstDataPageOffset();
      if (dictionaryPageOffset > 0 && dictionaryPageOffset < firstDataPageOffset) {
        // if there's a dictionary and it's before the first data page, start from there
        return dictionaryPageOffset;
      }
      return firstDataPageOffset;
    }
    

    您可以在此处查看上下文中的这些代码行:ParquetFileReader.readDictionaryColumnChunkMetaData.getStartingPos

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-12
      • 1970-01-01
      • 2016-03-12
      • 1970-01-01
      相关资源
      最近更新 更多