当读取Hive事务表时,Spark会抛出错误。

4

我正在尝试在Hive中执行select * from db.abc的操作,该Hive表是使用Spark加载的。

但是出现错误,显示如下:

Error: java.io.IOException: java.lang.IllegalArgumentException: bucketId out of range: -1 (state=,code=0)

当我使用以下属性时,我能够查询Hive:

set hive.mapred.mode=nonstrict;
set hive.optimize.ppd=true;
set hive.optimize.index.filter=true;
set hive.tez.bucket.pruning=true;
set hive.explain.user=false; 
set hive.fetch.task.conversion=none;

现在当我尝试使用Spark读取相同的Hive表db.abc时,我会收到以下错误:

如果客户端具备以下能力的话,那么他们才能访问这个表:CONNECTORREAD、HIVEFULLACIDREAD、HIVEFULLACIDWRITE、HIVEMANAGESTATS、HIVECACHEINVALIDATE、CONNECTORWRITE。这个表可能是一个由Hive管理的ACID表,或者需要Spark目前不支持的其他能力;在org.apache.spark.sql.catalyst.catalog.CatalogUtils$ .throwIfNoAccess (ExternalCatalogUtils.scala:280)和org.apache.spark.sql.hive.HiveTranslationLayerCheck$$anonfun$apply$1.applyOrElse(HiveTranslationLayerStrategies.scala:105)等位置将抛出异常。

请问我需要在spark-submit或shell中添加任何属性吗?还是有其他方法可以使用spark读取这个hive数据表?

hive表的样本格式:

  CREATE TABLE `hive``(                   |
|   `c_id` decimal(11,0),etc.........       
  ROW FORMAT SERDE                                   |
|   'org.apache.hadoop.hive.ql.io.orc.OrcSerde'      |
| WITH SERDEPROPERTIES (  
 STORED AS INPUTFORMAT                              |
|   'org.apache.hadoop.hive.ql.io.orc.OrcInputFormat'  |
| OUTPUTFORMAT                                       |
|   'org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat' |
 LOCATION                                           |
|  path= 'hdfs://gjuyada/bbts/scl/raw' |
| TBLPROPERTIES (                                    |
|   'bucketing_version'='2',                         |
|   'spark.sql.create.version'='2.3.2.3.1.0.0-78',   |
|   'spark.sql.sources.provider'='orc',              |
|   'spark.sql.sources.schema.numParts'='1',         |
|   'spark.sql.sources.schema.part.0'='{"type":"struct","fields":
[{"name":"Czz_ID","type":"decimal(11,0)","nullable":true,"metadata":{}},
{"name":"DzzzC_CD","type":"string","nullable":true,"metadata":{}},
{"name":"C0000_S_N","type":"decimal(11,0)","nullable":true,"metadata":{}},
{"name":"P_ _NB","type":"decimal(11,0)","nullable":true,"metadata":{}},
{"name":"C_YYYY","type":"string","nullable":true,"metadata":{}},"type":"string","nullable":true,"metadata":{}},{"name":"Cv_ID","type":"string","nullable":true,"metadata":{}},
|   'transactional'='true',                          |
|   'transient_lastDdlTime'='1574817059')  

请分享您正在尝试读取的Hive表信息。 - dassum
3个回答

6
您正在尝试将事务表(transactional = true)读入Spark的问题。
正式来说,Spark还不支持Hive-ACID表,需要将acid表的完整转储/增量转储到常规的hive orc/parquet分区表中,然后使用Spark读取数据。
有一个开放的Jira SPARK-15348用于添加对读取Hive ACID表的支持。
  • If you run major compaction on Acid table(from hive) then spark able to read base_XXX directories only but not delta directories SPARK-16996 addressed in this jira.

  • There are some workaround to read acid tables using SPARK-LLAP as mentioned in this link.

  • I think starting from HDP-3.X HiveWareHouseConnector is able to support to read HiveAcid tables.

  • You can create an snapshot of the transactional table as non transactional and then read the data from the table.

     **`create table <non_trans> stored as orc as select * from <transactional_table>`**
    
更新: 1. 创建一个外部hive表:
 CREATE external TABLE `<ext_tab_name>`(  
       <col_name>       <data_type>....etc
           )
    stored as orc
    location '<path>';

2. 然后使用现有的事务表数据覆盖到上述外部表中。
 insert overwrite table <ext_tab_name> select * from <transactional_tab_name>;

你能提供有关从事务表创建非事务表快照的信息吗?在创建 Hive 表时是否需要指定 transnational=false? - Db8
1
@user12763124,我想不需要了。如果您正在使用HDP-3,请确保快照表未启用事务!或者,您可以创建一个具有与事务表相同模式的外部表,然后通过从事务表中选择数据来将其插入到外部表中进行覆盖写入! - notNull
创建表<non_trans>存储为ORC,选择* from <transactional_table>。出现桶超出范围-1错误或者创建一个与事务表具有相同模式的外部表,也会出现相同的桶超出范围-1错误。 - Db8
是的,这个Hive表在Spark中最初创建时是事务性的。 - Db8
让我们在聊天中继续这个讨论 - notNull

2
你需要使用 TBLPROPERTIES ( 'transactional'='false' ) 来创建表。
CREATE TABLE your_table(
  `col` string, 
  `col2` string)
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
TBLPROPERTIES ( 
  'transactional'='false' 
)

1

请查看https://github.com/qubole/spark-acid,这是一个针对Apache Spark的Hive ACID数据源,可以让你读取Hive ACID/transaction表。

如果你使用的是Cloudera,请查看基于qubole项目的Hive Warehouse Connector (HWC):

  • HWC主页
  • 如果你可以将Spark应用程序运行为超级用户并且不需要授权,则可以使用更快的Spark Direct Reader模式:博客文章

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接