Как написать таблицу для улья от искры без использования соединителя хранилища в HDP 3.1 - PullRequest
1 голос
/ 16 октября 2019

при попытке использовать spark 2.3 на HDP 3.1 для записи в таблицу Hive без соединителя хранилища непосредственно в схему кустов с использованием:

spark-shell --driver-memory 16g --master local[3] --conf spark.hadoop.metastore.catalog.default=hive
val df = Seq(1,2,3,4).toDF
spark.sql("create database foo")
df.write.saveAsTable("foo.my_table_01")

завершается неудачно с:

Table foo.my_table_01 failed strict managed table checks due to the following reason: Table is marked as a managed table but is not transactional

, ноa:

val df = Seq(1,2,3,4).toDF.withColumn("part", col("value"))
df.write.partitionBy("part").option("compression", "zlib").mode(SaveMode.Overwrite).format("orc").saveAsTable("foo.my_table_02")

Spark с spark.sql("select * from foo.my_table_02").show работает просто отлично. Теперь перейдем к Hive / beeline:

0: jdbc:hive2://hostname:2181/> select * from my_table_02;
Error: java.io.IOException: java.lang.IllegalArgumentException: bucketId out of range: -1 (state=,code=0)

A

 describe extended my_table_02;

возвращает

 +-----------------------------+----------------------------------------------------+----------+
|          col_name           |                     data_type                      | comment  |
+-----------------------------+----------------------------------------------------+----------+
| value                       | int                                                |          |
| part                        | int                                                |          |
|                             | NULL                                               | NULL     |
| # Partition Information     | NULL                                               | NULL     |
| # col_name                  | data_type                                          | comment  |
| part                        | int                                                |          |
|                             | NULL                                               | NULL     |
| Detailed Table Information  | Table(tableName:my_table_02, dbName:foo, owner:hive/bd-sandbox.t-mobile.at@SANDBOX.MAGENTA.COM, createTime:1571201905, lastAccessTime:0, retention:0, sd:StorageDescriptor(cols:[FieldSchema(name:value, type:int, comment:null), FieldSchema(name:part, type:int, comment:null)], location:hdfs://bd-sandbox.t-mobile.at:8020/warehouse/tablespace/external/hive/foo.db/my_table_02, inputFormat:org.apache.hadoop.hive.ql.io.orc.OrcInputFormat, outputFormat:org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat, compressed:false, numBuckets:-1, serdeInfo:SerDeInfo(name:null, serializationLib:org.apache.hadoop.hive.ql.io.orc.OrcSerde, parameters:{path=hdfs://bd-sandbox.t-mobile.at:8020/warehouse/tablespace/external/hive/foo.db/my_table_02, compression=zlib, serialization.format=1}), bucketCols:[], sortCols:[], parameters:{}, skewedInfo:SkewedInfo(skewedColNames:[], skewedColValues:[], skewedColValueLocationMaps:{}), storedAsSubDirectories:false), partitionKeys:[FieldSchema(name:part, type:int, comment:null)], parameters:{numRows=0, rawDataSize=0, spark.sql.sources.schema.partCol.0=part, transient_lastDdlTime=1571201906, bucketing_version=2, spark.sql.create.version=2.3.2.3.1.0.0-78, totalSize=740, spark.sql.sources.schema.numPartCols=1, spark.sql.sources.schema.part.0={\"type\":\"struct\",\"fields\":[{\"name\":\"value\",\"type\":\"integer\",\"nullable\":true,\"metadata\":{}},{\"name\":\"part\",\"type\":\"integer\",\"nullable\":true,\"metadata\":{}}]}, numFiles=4, numPartitions=4, spark.sql.partitionProvider=catalog, spark.sql.sources.schema.numParts=1, spark.sql.sources.provider=orc, transactional=true}, viewOriginalText:null, viewExpandedText:null, tableType:MANAGED_TABLE, rewriteEnabled:false, catName:hive, ownerType:USER, writeId:-1) |

Как использовать spark для записи в улей без использованияконнектор хранилища , но все еще записываете в то же самое хранилище метаданных, которое позже можно прочитать с помощью улья? Насколько мне известно, внешние таблицы должны быть возможны (они не управляются, не ACID, не транзакционные), но я не уверен, как saveAsTable сказать, как с ними обращаться.

edit

связанные с этим вопросы:

Может быть обходной путь, как https://github.com/qubole/spark-acid как https://docs.cloudera.com/HDPDocuments/HDP3/HDP-3.1.4/integrating-hive/content/hive_hivewarehouseconnector_for_handling_apache_spark_data.html но мне не нравится идея использовать больше клейкой ленты, где я еще не видел масштабных тестов производительности. Кроме того, это означает изменение всех существующих заданий на запуск.

Фактически Не удается сохранить таблицу в метасольве улья, HDP 3.0 сообщает о проблемах с большими фреймами данных и соединителем хранилища.

edit

Я только что нашел https://community.cloudera.com/t5/Support-Questions/Spark-hive-warehouse-connector-not-loading-data-when-using/td-p/243613

И:

execute () vs executeQuery ()

ExecuteQuery () всегда будет использоватьHiveserver2-интерактивный / LLAP, поскольку он использует быстрый протокол ARROW. Использование его, когда URL-адрес jdbc указывает на не-LLAP Hiveserver2, приведет к ошибке.

Execute () использует JDBC и не имеет этой зависимости от LLAP, но имеет встроенное ограничение для возврата только 1000 записейМаксимум. Но для большинства запросов (INSERT INTO ... SELECT, count, sum, medium) это не проблема.

Но не мешает ли это высокопроизводительной совместимости между кустом и искрой? Особенно, если для крупномасштабного ETL недостаточно узлов LLAP.

На самом деле это действительно так. Этот параметр можно настроить на https://github.com/hortonworks-spark/spark-llap/blob/26d164e62b45cfa1420d5d43cdef13d1d29bb877/src/main/java/com/hortonworks/spark/sql/hive/llap/HWConf.java#L39,, хотя я не уверен в влиянии на производительность увеличения этого значения

Ответы [ 3 ]

0 голосов
/ 16 октября 2019

Внутри Ambari простое отключение опции создания транзакционных таблиц по умолчанию решает мою проблему.

, дважды установленное в ложь (tez, llap)

hive.strict.managed.tables = false

и включаемое вручную в каждом table property при желании (использовать транзакционную таблицу).

0 голосов
/ 17 октября 2019

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

Что-то вроде этих строк:

val df:DataFrame = ...
val externalPath = "/warehouse/tablespace/external/hive/my_db.db/my_table"
import com.hortonworks.hwc.HiveWarehouseSession
val hive = HiveWarehouseSession.session(spark).build()
dxx.write.partitionBy("part_col").option("compression", "zlib").mode(SaveMode.Overwrite).orc(externalPath)
val columns = dxx.drop("part_col").schema.fields.map(field => s"${field.name} ${field.dataType.simpleString}").mkString(", ")
val ddl =
      s"""
         |CREATE EXTERNAL TABLE my_db.my_table ($columns)
         |PARTITIONED BY (part_col string)
         |STORED AS ORC 
         |Location '$externalPath'
       """.stripMargin

hive.execute(ddl)
hive.execute(s"MSCK REPAIR TABLE $tablename SYNC PARTITIONS")

К сожалению, это выдает:

java.sql.SQLException: The query did not generate a result set!

от HWC

0 голосов
/ 16 октября 2019

Вы пробовали

    data.write \
        .mode("append") \
        .insertInto("tableName")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...