Почему страница словаря смещена в 0 для кодировки `plain_dictionary`? - PullRequest
1 голос
/ 18 марта 2019

Паркет создан 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 для обоих столбцов?

Если я проверю, используя pyarrow v0.11.1, который использует parquet-cpp v1.5.1, он скажет мне has_dictionary_page: False & dictionary_page_offset: None

У него есть страница словаря или нет?

1 Ответ

1 голос
/ 18 марта 2019

Смещение первой страницы данных всегда больше, чем смещение словаря. Другими словами, сначала идет словарь, а затем - страницы данных. Есть два поля метаданных, предназначенных для хранения этих смещений: dictionary_page_offset (он же DO) и data_page_offset (он же FPO). К сожалению, эти поля метаданных не заполнены правильно parquet-mr.

Например, если словарь начинается со смещения 1000, а первая страница данных начинается со смещения 2000, то правильные значения будут:

  • dictionary_page_offset = 1000
  • data_page_offset = 2000

Вместо этого паркет-мр магазины

  • dictionary_page_offset = 0
  • data_page_offset = 1000

Применительно к вашему примеру это означает, что, несмотря на то, что инструменты для работы с паркетом показывают 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.readDictionary , ColumnChunkMetaData.getStartingPos .

...