Каковы различия между saveAsTable и insertInto в разных SaveMode (s)?

Я пытаюсь записать DataFrame в таблицу Hive (на S3) в режиме Overwrite (необходимо для моего приложения), и мне нужно выбрать один из двух методов DataFrameWriter (Spark/Scala). Из того, что я могу прочитать в документации, df.write.saveAsTable отличается от df.write.insertInto в следующих отношениях:

  • saveAsTable использует разрешение на основе имени столбца, а insertInto использует разрешение на основе позиции
  • В режиме saveAsTable уделяет больше внимания базовой схеме существующей таблицы для принятия определенных решений.

В целом, у меня saveAsTable впечатление, что saveAsTable - это просто более умная версия insertInto. В качестве альтернативы, в зависимости от insertInto использования, можно предпочесть insertInto

Но каждый ли из этих методов сопровождается некоторыми оговорками, такими как saveAsTable производительности в случае saveAsTable (поскольку он содержит больше функций)? Есть ли другие различия в их поведении помимо того, что сказано (не очень ясно) в документах?


EDIT-1

Документация говорит об этом относительно insertInto

Вставляет содержимое DataFrame в указанную таблицу

и это для saveAsTable

Если таблица уже существует, поведение этой функции зависит от режима сохранения, заданного функцией mode

Теперь я могу перечислить свои сомнения

  • Всегда ли insertInto ожидает, что таблица будет существовать?
  • SaveMode ли SaveMode на insertInto?
  • Если ответ выше, то да, тогда
    • какие различия между saveAsTable с SaveMode.Append и insertInto учитывая, что таблица уже существует?
    • insertInto ли смысл insertInto с SaveMode.Overwrite?

Ответ 1

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ Я уже некоторое время insertInto и хотя я далеко не эксперт в этой области, я делюсь результатами для большего блага.

Всегда ли insertInto ожидает, что таблица будет существовать?

Да (по названию таблицы и базе данных).

Кроме того, не все таблицы могут быть вставлены, то есть (постоянная) таблица, временное представление или временное глобальное представление хороши, но не:

  1. стол с ковкой

  2. таблица на основе RDD

Влияет ли SaveModes на insertInto?

(Это недавно мой вопрос тоже!)

Да, но только SaveMode.Overwrite. После того, как вы подумаете о insertInto в другие 3 режима сохранения, не имеет особого смысла (так как он просто вставляет набор данных).

какие различия между saveAsTable с SaveMode.Append и insertInto, учитывая, что таблица уже существует?

Это очень хороший вопрос! Я бы сказал, нет, но давайте посмотрим только на один пример (надеясь, что это что-то доказывает).

scala> spark.version
res13: String = 2.4.0-SNAPSHOT

sql("create table my_table (id long)")
scala> spark.range(3).write.mode("append").saveAsTable("my_table")
org.apache.spark.sql.AnalysisException: The format of the existing table default.my_table is 'HiveFileFormat'. It doesn't match the specified format 'ParquetFileFormat'.;
  at org.apache.spark.sql.execution.datasources.PreprocessTableCreation$$anonfun$apply$2.applyOrElse(rules.scala:117)
  at org.apache.spark.sql.execution.datasources.PreprocessTableCreation$$anonfun$apply$2.applyOrElse(rules.scala:76)
...
scala> spark.range(3).write.insertInto("my_table")
scala> spark.table("my_table").show
+---+
| id|
+---+
|  2|
|  0|
|  1|
+---+

Имеет ли смысл вставка с SaveMode. Overwrite?

Я думаю, так как он уделяет так много внимания SaveMode.Overwrite. Он просто воссоздает целевую таблицу.

spark.range(3).write.mode("overwrite").insertInto("my_table")
scala> spark.table("my_table").show
+---+
| id|
+---+
|  1|
|  0|
|  2|
+---+

Seq(100, 200, 300).toDF.write.mode("overwrite").insertInto("my_table")
scala> spark.table("my_table").show
+---+
| id|
+---+
|200|
|100|
|300|
+---+

Ответ 2

Еще один важный момент, который я учитываю при вставке данных в динамическую многораздельную таблицу EXISTING Hive из spark 2.xx:

df.write.mode("append").insertInto("dbName"."tableName")

Приведенная выше команда будет внутренне отображать данные в вашем "df" и добавлять только новые разделы к существующей таблице.

Надеюсь, это добавляет еще один момент в решении, когда использовать "insertInto".

Ответ 3

Недавно я начал преобразовывать свои скрипты Hive в Spark, и я все еще учусь.

Есть одно важное поведение, которое я заметил с saveAsTable и insertInto, которое не обсуждалось.

df.write.mode("overwrite"). saveAsTable ("schema.table") удаляет существующую таблицу "schema.table" и воссоздает новую таблицу на основе схемы 'df'. Схема существующей таблицы становится неактуальной и не должна совпадать с df. Меня укусило это поведение, так как моя существующая таблица была ORC, а созданная новая таблица была паркетной (Spark Default).

df.write.mode("overwrite"). insertInto ("schema.table") не удаляет существующую таблицу и ожидает, что схема существующей таблицы будет совпадать со схемой 'df'.

Я проверил время создания таблицы, используя оба параметра, и подтвердил поведение.

Исходная таблица хранится как ORC - ср. 04 сентября 21:27:33 GMT 2019

После saveAsTable (хранилище изменено на Parquet) - Ср 04 сен 21:56:23 GMT 2019 (Время создания изменено)

Исходная таблица удаленных и воссозданных (ORC) - ср. 04 сентября 21:57:38 GMT 2019

После insertInto (Still ORC) - ср. 04 сентября 21:57:38 GMT 2019 (время создания не изменено)