Эволюция схемы в паркетном формате

В настоящее время мы используем формат данных Avro в производстве. из нескольких хороших моментов, использующих Avro, мы знаем, что он хорош в эволюции схемы.

Теперь мы оцениваем формат паркета из-за его эффективности при чтении случайных столбцов. Поэтому, прежде чем двигаться вперед, мы все еще заботимся о эволюции схемы.

Кто-нибудь знает, возможна ли эволюция схемы в паркете, если да Как это возможно, если нет, то Почему нет.

Некоторые ресурсы утверждают, что это возможно, но может добавлять столбцы только в конце.

Что это значит?

Ответ 1

Эволюция схемы может быть (очень) дорогой.

Чтобы выяснить схему, вам, в основном, нужно прочитать все ваши файлы паркета и согласовать/объединить их схемы во время чтения, что может быть дорогостоящим в зависимости от того, сколько файлов или/и сколько столбцов находится в наборе данных.

Таким образом, начиная с Spark 1.5, они по умолчанию отключили объединение схем. Вы всегда можете включить его снова.

Поскольку объединение схем является относительно дорогой операцией, а не необходимость в большинстве случаев, мы отключили его по умолчанию, начиная с 1.5.0.

Без эволюции схемы вы можете читать схему из одного файла паркета, а во время чтения остальных файлов предполагать, что она останется прежней.

Эволюция схемы паркета зависит от реализации.

У улья, например, есть ручка parquet.column.index.access=false что вы можете настроить отображение схемы по именам столбцов, а не по индексам столбцов.

Тогда вы можете удалить столбцы, а не просто добавить.

Как я уже говорил выше, это зависит от реализации, например, Impala не будет правильно читать такие паркетные таблицы (исправлено в недавнем выпуске Impala 2.6) [Ссылка].

Apache Spark, начиная с версии 2.0.2, поддерживает только добавление столбцов: [ссылка]

Пользователи могут начать с простой схемы и постепенно добавлять столбцы к схеме по мере необходимости. Таким образом, пользователи могут в конечном итоге с несколькими Паркетные файлы с разными, но взаимно совместимыми схемами. Источник данных для паркета теперь может автоматически обнаруживать этот случай и объединить схемы всех этих файлов.

PS: Я видел, что некоторые люди делают более гибкими изменения схемы, поскольку они создают представление поверх фактических таблиц паркета, которое отображает две (или более) разные, но совместимые схемы, в одну общую схему.

Допустим, вы добавили одно новое поле (registration_date) и удалили другой столбец (last_login_date) в своем новом выпуске, тогда это будет выглядеть следующим образом:

CREATE VIEW datamart.unified_fact_vw
AS
SELECT f1..., NULL as registration_date 
FROM datamart.unified_fact_schema1 f1
UNION ALL
SELECT f2..., NULL as last_login_date
FROM datamart.unified_fact_schema2 f2
;

У тебя есть идея. Приятно, что он будет работать одинаково на всех sql на диалектах Hadoop (как я уже упоминал выше, Hive, Impala и Spark) и при этом будет иметь все преимущества таблиц Parquet (хранение в столбцах, push-down и т.д.).

P.P.S: добавление некоторой информации относительно сводных файлов common_metadata, которые Spark может создать, чтобы сделать этот ответ более полным.

Посмотрите на SPARK-15719

Сводные файлы паркета в настоящее время не особенно полезны, так как

 - when schema merging is disabled, we assume 
   schema of all Parquet part-files are identical, 
   thus we can read the footer from any part-files.

- when schema merging is enabled, we need to read footers 
  of all files anyway to do the merge.

On the other hand, writing summary files can be expensive,
because footers of all part-files must be read and merged. 
This is particularly costly when appending a small dataset 
to a large existing Parquet dataset.

Так что некоторые моменты против включения common_metadata:

  • Когда каталог состоит из файлов Parquet со смесью различных схем, _common_metadata позволяет читателям выяснить разумную схему для всего каталога, не читая схемы каждого отдельного файла. Поскольку Hive и Impala могут получить доступ к схеме SQL для указанных файлов из метастаза Hive, они могут сразу же начать обработку отдельных файлов и сопоставлять каждый из них со схемой SQL при чтении, вместо того, чтобы предварительно изучить их общую схему. Это делает функцию общих метаданных ненужной для Hive и Impala.

  • Несмотря на то, что Spark обрабатывает файлы Parquet без схемы SQL (если только не использует SparkSQL) и, следовательно, теоретически может извлечь выгоду из _common_metadata, эта функция все еще считается бесполезной и, следовательно, по умолчанию отключена в SPARK-15719.

  • Даже если эта функция была полезна для запросов, она все еще является бременем во время написания. Необходимо поддерживать метаданные, которые не только медленны, но и подвержены гоночным условиям и другим проблемам параллелизма, страдают от отсутствия гарантий атомарности и легко приводят к проблемам с правильностью данных из-за устаревших или несовместимых метаданных.

  • Эта функция недокументирована и, по-видимому, считается устаревшей (во-первых, "кажется, что она есть", потому что, во-первых, она вообще никогда не поддерживалась официально, а не поддерживаемая функция также не может устареть).

  • От одного из инженеров Cloudera: "Я не знаю, изменилось ли поведение на стороне чтения, чтобы не смотреть на каждый нижний колонтитул, если присутствует файл common_metadata. Но независимо от того, запись этого файла в первую очередь является ОГРОМНЫМ узким местом"., и вызвало много проблем для наших клиентов. Я действительно настоятельно рекомендую, чтобы они не пытались сгенерировать этот файл метаданных. "

  • Файлы "_common_metadata" и "_metadata" являются специфичными для Spark и не пишутся, например, Impala и Hive и, возможно, другими движками.

Сводные файлы метаданных в Spark могут по-прежнему иметь свои варианты использования, хотя - когда нет параллелизма и других проблем, описанных выше - например, некоторые потоковые сценарии использования - я думаю, поэтому эта функция не была полностью удалена из Spark.

Ответ 2

В дополнение к ответу выше, другой вариант - установить

"spark.hadoop.parquet.enable.summary-metadata" to "true"

При создании файлов создаются сводные файлы со схемой. При сохранении вы увидите файлы сводных файлов '_metadata' и '_common_metadata'. _common_metadata - это сжатая схема, которая читается каждый раз, когда вы читаете файл паркета. Это делает чтение очень быстрым, поскольку у вас уже есть схема. Spark ищет эти файлы схемы, если они есть, чтобы получить схему.

Обратите внимание, что это делает запись очень медленной, так как Spark должен объединить схему всех файлов и создать этот файл схемы.

У нас была похожая ситуация, когда схема паркета изменилась. То, что мы сделали, - установили вышеуказанную конфигурацию на true на некоторое время после изменения схемы, чтобы сгенерировать файлы схемы, а затем вернули ее на false. В течение некоторого времени нам приходилось идти на компромисс с медленной записью, но после того, как файлы схемы были сгенерированы, установка в false послужила цели. И с бонусом чтения файлов быстрее.