从 Hive 查询时,来自分区 table 的数据不显示
Data from partitioned table does not show up when queried from Hive
请注意这个问题不是与this one的重复!我不使用 Spark SQL 进行分区!我正在保存单个镶木地板文件!
我也在使用不支持 Hive 风格的 DatabricksSQL.
我在 Hive 中有一个 table(我正在使用 Databricks),它包含两个分区。它看起来像这样:
CREATE TABLE foo_test (`col0` STRING, `col1` STRING, `col2` STRING, `datestamp` STRING)
USING parquet
OPTIONS (
`serialization.format` '1'
)
PARTITIONED BY (datestamp)
编辑: *这也是调用show create table foo_test;
的结果
我已经用 Spark 手动向这个 table 添加了两个分区:
df = spark.read.csv(file_path.format(datestamp), header=True, inferSchema=True)
partitionPath = "/mnt/foo_test/datestamp={}/".format(datestamp)
df.coalesce(1).write.parquet(partitionPath, mode="overwrite")
/mnt/foo_test/datestamp=20180101/
/mnt/foo_test/datestamp=20180102/
如果我用 Spark 加载数据,我可以看到它在那里:
spark.read.option("mergeSchema", True).parquet("/mnt/foo_test").show()
+----+----+----+----+---------+
|col0|col1|col2|col3|datestamp|
+----+----+----+----+---------+
| foo| bar| baz| 1| 20180102|
| xul| qux| wom| 2| 20180102|
| bar| foo| baz| 1| 20180102|
| qux| xul| wom| 2| 20180102|
| foo| bar| baz|null| 20180101|
| xul| qux| wom|null| 20180101|
| bar| foo| baz|null| 20180101|
| qux| xul| wom|null| 20180101|
+----+----+----+----+---------+
我的问题是,如果我 运行 针对此 Hive SQL 查询 table 它 returns 什么都没有:
SELECT * FROM foo_test;
OK
即使在手动添加分区之后:
spark.sql("ALTER TABLE foo_test ADD IF NOT EXISTS PARTITION (datestamp=20180102)")
并修复 table:
MSCK REPAIR TABLE foo_test;
我可以看到根据 Hive 存在分区:
SHOW PARTITIONS foo_test;
partition
datestamp=20180102
datestamp=20180101
但是 SELECT
returns 什么都没有。
这是我的table的描述:
col0 string null
col1 string null
col2 string null
datestamp string null
# Partition Information
# col_name data_type comment
datestamp string null
# Detailed Table Information
Database default
Table foo_test
Owner root
Created Thu Apr 26 12:25:06 UTC 2018
Last Access Thu Jan 01 00:00:00 UTC 1970
Type MANAGED
Provider parquet
Table Properties [transient_lastDdlTime=1524745506]
Location dbfs:/user/hive/warehouse/foo_test
Serde Library org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe
InputFormat org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat
OutputFormat org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat
Storage Properties [serialization.format=1]
Partition Provider Catalog
这可能是什么问题?
I do not use Spark SQL for partitioning!
我不同意。这不是 Hive table 定义:
CREATE TABLE foo_test (`col0` STRING, `col1` STRING, `col2` STRING, `datestamp` STRING)
USING parquet
OPTIONS (
`serialization.format` '1'
)
PARTITIONED BY (datestamp)
这是一个 Spark table 定义。
Hive table definition would be:
CREATE TABLE foo_test (`col0` STRING, `col1` STRING, `col2` STRING)
PARTITIONED BY (`datestamp` STRING)
STORED AS PARQUET
因此您确实使用了 Spark 分区,并且如 the question you've linked, and further in the linked JIRA ticket 中所述,Spark 和 Hive 分区方案不兼容..
请注意,SparkSession.sql
中同时支持 Hive 和 Spark,只要启用了 Hive 支持,当 SparkSession
已初始化(Databricks 平台上的默认设置)时。
也不清楚你为什么写到/mnt/foo_test/datestamp={}
这里,这可能是问题的另一个来源。如果你想使用本地文件 API(你为什么要这样做?),Databricks 默认将它安装在 /dbfs
.
上
由于您在没有位置的情况下调用 ADD PARTITIONS
,它使用 table 的根路径(dbfs:/user/hive/warehouse/foo_test
基于 DESCRIBE
输出),因此如果您决定使用本地 API,并使用默认配置,您应该写入
/dbfs/user/hive/warehouse/foo_test/datestamp=20180102
如果您使用非标准配置,最好将其包含在您的问题中。
Table 定义指向不同的位置
Location dbfs:/user/hive/warehouse/foo_test
它应该指向以下位置/mnt/foo_test
使用位置
寻找配置单元创建 table
当您在配置单元使用中创建 table 时:
CREATE TABLE foo_test (`col0` STRING, `col1` STRING, `col2` STRING)
PARTITIONED BY (`datestamp` STRING)
stored as PARQUET
location '/mnt/foo_test';
您可以使用 spark write with partition :
df.repartition($"datestamp").partitionBy("datestamp").write.parquet(partitionPath, mode="overwrite")
这将使用分区路径 /mnt/foo_test/datestamp=***/.
写入配置单元 table
希望对您有所帮助
您没有在 CREATE TABLE
定义中设置位置,也没有设置新添加分区的位置。
在您的 table 定义中,您应该将其定义为外部 table 并为其提供数据路径,作为 LOCATION
或 PATH
参数.然后 MSCK REPAIR TABLE
应该正确添加分区。
对于ALTER TABLE
命令,需要设置LOCATION
参数。在该片段中,您只是告诉 table "there's a partition date=20180102" 而没有告诉它数据在哪里。
每 https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-AddPartitions
spark.sql("ALTER TABLE foo_test ADD IF NOT EXISTS PARTITION (datestamp=20180102) location '/mnt/foo_test/datestamp=20180102/' ")
请注意这个问题不是与this one的重复!我不使用 Spark SQL 进行分区!我正在保存单个镶木地板文件!
我也在使用不支持 Hive 风格的 DatabricksSQL.
我在 Hive 中有一个 table(我正在使用 Databricks),它包含两个分区。它看起来像这样:
CREATE TABLE foo_test (`col0` STRING, `col1` STRING, `col2` STRING, `datestamp` STRING)
USING parquet
OPTIONS (
`serialization.format` '1'
)
PARTITIONED BY (datestamp)
编辑: *这也是调用show create table foo_test;
我已经用 Spark 手动向这个 table 添加了两个分区:
df = spark.read.csv(file_path.format(datestamp), header=True, inferSchema=True)
partitionPath = "/mnt/foo_test/datestamp={}/".format(datestamp)
df.coalesce(1).write.parquet(partitionPath, mode="overwrite")
/mnt/foo_test/datestamp=20180101/
/mnt/foo_test/datestamp=20180102/
如果我用 Spark 加载数据,我可以看到它在那里:
spark.read.option("mergeSchema", True).parquet("/mnt/foo_test").show()
+----+----+----+----+---------+
|col0|col1|col2|col3|datestamp|
+----+----+----+----+---------+
| foo| bar| baz| 1| 20180102|
| xul| qux| wom| 2| 20180102|
| bar| foo| baz| 1| 20180102|
| qux| xul| wom| 2| 20180102|
| foo| bar| baz|null| 20180101|
| xul| qux| wom|null| 20180101|
| bar| foo| baz|null| 20180101|
| qux| xul| wom|null| 20180101|
+----+----+----+----+---------+
我的问题是,如果我 运行 针对此 Hive SQL 查询 table 它 returns 什么都没有:
SELECT * FROM foo_test;
OK
即使在手动添加分区之后:
spark.sql("ALTER TABLE foo_test ADD IF NOT EXISTS PARTITION (datestamp=20180102)")
并修复 table:
MSCK REPAIR TABLE foo_test;
我可以看到根据 Hive 存在分区:
SHOW PARTITIONS foo_test;
partition
datestamp=20180102
datestamp=20180101
但是 SELECT
returns 什么都没有。
这是我的table的描述:
col0 string null
col1 string null
col2 string null
datestamp string null
# Partition Information
# col_name data_type comment
datestamp string null
# Detailed Table Information
Database default
Table foo_test
Owner root
Created Thu Apr 26 12:25:06 UTC 2018
Last Access Thu Jan 01 00:00:00 UTC 1970
Type MANAGED
Provider parquet
Table Properties [transient_lastDdlTime=1524745506]
Location dbfs:/user/hive/warehouse/foo_test
Serde Library org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe
InputFormat org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat
OutputFormat org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat
Storage Properties [serialization.format=1]
Partition Provider Catalog
这可能是什么问题?
I do not use Spark SQL for partitioning!
我不同意。这不是 Hive table 定义:
CREATE TABLE foo_test (`col0` STRING, `col1` STRING, `col2` STRING, `datestamp` STRING)
USING parquet
OPTIONS (
`serialization.format` '1'
)
PARTITIONED BY (datestamp)
这是一个 Spark table 定义。
Hive table definition would be:
CREATE TABLE foo_test (`col0` STRING, `col1` STRING, `col2` STRING)
PARTITIONED BY (`datestamp` STRING)
STORED AS PARQUET
因此您确实使用了 Spark 分区,并且如 the question you've linked, and further in the linked JIRA ticket 中所述,Spark 和 Hive 分区方案不兼容..
请注意,SparkSession.sql
中同时支持 Hive 和 Spark,只要启用了 Hive 支持,当 SparkSession
已初始化(Databricks 平台上的默认设置)时。
也不清楚你为什么写到/mnt/foo_test/datestamp={}
这里,这可能是问题的另一个来源。如果你想使用本地文件 API(你为什么要这样做?),Databricks 默认将它安装在 /dbfs
.
由于您在没有位置的情况下调用 ADD PARTITIONS
,它使用 table 的根路径(dbfs:/user/hive/warehouse/foo_test
基于 DESCRIBE
输出),因此如果您决定使用本地 API,并使用默认配置,您应该写入
/dbfs/user/hive/warehouse/foo_test/datestamp=20180102
如果您使用非标准配置,最好将其包含在您的问题中。
Table 定义指向不同的位置
Location dbfs:/user/hive/warehouse/foo_test
它应该指向以下位置/mnt/foo_test
使用位置
寻找配置单元创建 table当您在配置单元使用中创建 table 时:
CREATE TABLE foo_test (`col0` STRING, `col1` STRING, `col2` STRING)
PARTITIONED BY (`datestamp` STRING)
stored as PARQUET
location '/mnt/foo_test';
您可以使用 spark write with partition :
df.repartition($"datestamp").partitionBy("datestamp").write.parquet(partitionPath, mode="overwrite")
这将使用分区路径 /mnt/foo_test/datestamp=***/.
写入配置单元 table希望对您有所帮助
您没有在 CREATE TABLE
定义中设置位置,也没有设置新添加分区的位置。
在您的 table 定义中,您应该将其定义为外部 table 并为其提供数据路径,作为 LOCATION
或 PATH
参数.然后 MSCK REPAIR TABLE
应该正确添加分区。
对于ALTER TABLE
命令,需要设置LOCATION
参数。在该片段中,您只是告诉 table "there's a partition date=20180102" 而没有告诉它数据在哪里。
每 https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-AddPartitions
spark.sql("ALTER TABLE foo_test ADD IF NOT EXISTS PARTITION (datestamp=20180102) location '/mnt/foo_test/datestamp=20180102/' ")