我正在使用带有scala的spark来读取特定的Hive分区。分区为year
,month
,day
,a
和b
scala> spark.sql("select * from db.table where year=2019 and month=2 and day=28 and a='y' and b='z'").show
但是我得到这个错误:
org.apache.spark.SparkException:由于阶段失败而导致作业中止:阶段0.0中的任务236失败4次,最近一次失败:阶段0.0中的任务236.3丢失(TID 287,服务器,执行器17):org.apache .hadoop.security.AccessControlException:权限被拒绝:user = user,access = READ,inode =“ / path-to-table / table / year = 2019 / month = 2 / day = 27 / a = w / b = x / part-00002“:user:group:-rw-rw ----
如您所见,spark试图读取一个不同的分区,而我在那里没有权限。
不应该这样,因为我创建了一个过滤器,而这个过滤器是我的分区。
我用Hive尝试了相同的查询,并且运行正常(无访问问题)
Hive> select * from db.table where year=2019 and month=2 and day=28 and a='y' and b='z';
为什么spark试图读取此分区,而Hive没有读取?
我缺少一个Spark配置吗?
编辑:更多信息
某些文件是使用Hive创建的,其他文件是从一台服务器复制并以不同的权限粘贴到我们的服务器(我们无法更改权限),那么它们应该已经刷新了数据。
我们正在使用:
cloudera 5.13.2.1
hive 1.1.0
spark 2.3.0
hadoop 2.6.0
scala 2.11.8
java 1.8.0_144
显示创建表
|CREATE EXTERNAL TABLE Columns and type
PARTITIONED BY (`year` int COMMENT '*', `month` int COMMENT '*', `day` int COMMENT '*', `a` string COMMENT '*', `b` string COMMENT '*')
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
WITH SERDEPROPERTIES (
'serialization.format' = '1'
)
STORED AS
INPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION 'hdfs://path'
TBLPROPERTIES (
'transient_lastDdlTime' = '1559029332'
)
|
答案 0 :(得分:2)
Spark中的镶木配置单元表可以使用以下2条读取流-
蜂巢流量-
将spark.sql.hive.convertMetastoreParquet
设置为false
时使用。为了在这种情况下可以进行分区修剪,您必须设置spark.sql.hive.metastorePartitionPruning=true
。
spark.sql.hive.metastorePartitionPruning:为true时,某些谓词 会被下推到Hive Metastore中,因此无法匹配 分区可以更早地消除。这只会影响Hive表 未转换为文件源关系(请参阅 HiveUtils.CONVERT_METASTORE_PARQUET和 HiveUtils.CONVERT_METASTORE_ORC了解更多信息
数据源流-默认情况下,此流已启用分区修剪。
答案 1 :(得分:1)
当metastore没有partition列的分区值时,可能会发生这种情况。 我们可以从Spark运行
ALTER TABLE db.table RECOVER PARTITIONS
然后重新运行相同的查询。
答案 2 :(得分:-1)
您将无法读取无法使用Spark-Hive API对其所有分区进行访问的表中的特殊分区。 Spark正在使用Hive表访问权限,在Hive中,您需要对表具有完全访问权限。
不能将spark-hive视为unix访问的原因。如果需要这样做,请使用spark.csv(或任何格式)。然后读取基于文件的数据。
您可以简单地使用spark.csv.read("/path-to-table/table/year=2019/month=2/day=27/a=w/b=x/part-")
如果您需要验证我的答案,请忽略spark并尝试在Hive
shell中运行相同的查询,它将不能作为配置单元的一部分。