如何在不使用hdp3.1中的仓库连接器的情况下从spark向hive写入表

flvtvl50  于 2021-06-25  发布在  Hive
关注(0)|答案(3)|浏览(507)

尝试使用hdp 3.1上的spark 2.3在没有仓库连接器的情况下将数据写入配置单元表时,请使用:

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/直线:

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)

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在不使用仓库连接器的情况下向hive写入数据,但仍然向同一个metastore写入数据,稍后hive可以读取这些数据?据我所知,外部表应该是可能的(您的表不是托管的,不是acid的,也不是事务性的),但是我不知道如何告诉 saveAsTable 如何处理这些。

编辑

相关问题:
https://community.cloudera.com/t5/support-questions/in-hdp-3-0-can-t-create-hive-table-in-spark-failed/td-p/202647
通过spark加载的表在Hive中不可访问
在那里设置答案中建议的属性并不能解决我的问题
似乎也是一个错误:https://issues.apache.org/jira/browse/hive-20593
可能是像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 但是我不喜欢在我还没有看到任何大规模性能测试的地方使用更多的胶带。此外,这意味着改变所有现有的Spark工作。
事实上,hdp3.0无法将表保存到hivemetastore,它报告了大Dataframe和仓库连接器的问题。

编辑

我刚发现https://community.cloudera.com/t5/support-questions/spark-hive-warehouse-connector-not-loading-data-when-using/td-p/243613
以及:
execute()与executequery()
executequery()将始终使用hiveserver2交互式/llap,因为它使用快速箭头协议。当jdbc url指向非llap hiveserver2时使用它将产生错误。
execute()使用jdbc,不依赖于llap,但是有一个内置的限制,最多只能返回1.000条记录,但是对于大多数查询(插入到。。。选择、计数、求和、平均)这不是问题。
但这难道不会扼杀hive和spark之间的高性能互操作性吗?尤其是当没有足够的llap节点可用于大规模etl时。
事实上,这是真的。可以在以下位置配置此设置:https://github.com/hortonworks-spark/spark-llap/blob/26d164e62b45cfa1420d5d43cdef13d1d29bb877/src/main/java/com/hortonworks/spark/sql/hive/llap/hwconf.java#l39,但我不确定增加此值对性能的影响

u4vypkhs

u4vypkhs1#

在ambari内部,只需在默认情况下禁用创建事务表的选项就可以解决我的问题。
设置为假两次(tez,llap)

hive.strict.managed.tables = false

并在每个 table property 如果需要(使用事务表)。

9fkzdhlc

9fkzdhlc2#

创建一个外部表(作为解决方法)似乎是我的最佳选择。这仍然需要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

xdyibdwo

xdyibdwo3#

你试过了吗

data.write \
        .mode("append") \
        .insertInto("tableName")

相关问题