Данные из секционированной таблицы не отображаются при запросе из Hive - PullRequest
0 голосов
/ 26 апреля 2018

Обратите внимание, что этот вопрос не является дубликатом этого ! Я не использую Spark SQL для разметки! Я сохраняю отдельные файлы паркета!

Я также использую Databricks , который не поддерживает SQL со вкусом Hive.

У меня есть таблица в Hive (я использую 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 вручную:

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|
+----+----+----+----+---------+

Моя проблема в том, что, если я запускаю SQL-запрос к этой таблице Hive, он ничего не возвращает:

SELECT * FROM foo_test;

OK

Даже после добавления раздела вручную:

spark.sql("ALTER TABLE foo_test ADD IF NOT EXISTS PARTITION (datestamp=20180102)")

и ремонт стола:

MSCK REPAIR TABLE foo_test;

Я вижу, что разделы присутствуют в соответствии с Hive:

SHOW PARTITIONS foo_test;

partition
datestamp=20180102
datestamp=20180101

но SELECT ничего не возвращает.

Это описание моей таблицы:

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

В чем здесь проблема?

Ответы [ 4 ]

0 голосов
/ 26 апреля 2018

Вы не задаете местоположение в своем определении CREATE TABLE и не устанавливаете местоположение вновь добавленного раздела.

В определении таблицы вы должны определить ее как внешнюю таблицу и указать путь к вашим данным в виде параметра LOCATION или PATH. Тогда MSCK REPAIR TABLE должен правильно добавить разделы.

Для команды ALTER TABLE необходимо установить параметр LOCATION. В этом фрагменте вы просто сообщаете таблице «дата раздела = 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/' ")

0 голосов
/ 26 апреля 2018

Определение таблицы указывает на другое местоположение

Location    dbfs:/user/hive/warehouse/foo_test  

Он должен указывать на следующее местоположение /mnt/foo_test

Найдите улей для создания таблицы с местоположением

0 голосов
/ 26 апреля 2018

при создании таблицы в улье:

CREATE TABLE foo_test (`col0` STRING, `col1` STRING, `col2` STRING)
PARTITIONED BY (`datestamp` STRING)
stored as PARQUET
location '/mnt/foo_test';

Вы можете использовать со спарк-записью с разделом:

df.repartition($"datestamp").partitionBy("datestamp").write.parquet(partitionPath, mode="overwrite")

это запишет в таблицу кустов с разделенным путем /mnt/foo_test/datestamp=***/.

Я надеюсь, что это поможет

0 голосов
/ 26 апреля 2018

Я не использую Spark SQL для разбиения!

Я должен не согласиться. Это не определение таблицы Hive:

CREATE TABLE foo_test (`col0` STRING, `col1` STRING, `col2` STRING, `datestamp` STRING)
USING parquet
OPTIONS (
  `serialization.format` '1'
)
PARTITIONED BY (datestamp)

Это определение таблицы Spark.

Определение таблицы Hive будет :

CREATE TABLE foo_test (`col0` STRING, `col1` STRING, `col2` STRING)
PARTITIONED BY (`datestamp` STRING)
STORED AS PARQUET

Таким образом, вы используете разделение Spark, и, как уже объяснено в вопрос, который вы связали , а также в связанном билете JIRA , схемы разделения Spark и Hive несовместимы ..

Обратите внимание, что Hive и Spark поддерживаются в SparkSession.sql, пока включена поддержка Hive, когда инициализирована SparkSession (по умолчанию на платформе Databricks).

Также неясно, почему вы пишете здесь /mnt/foo_test/datestamp={}, что может стать еще одним источником проблем. Если вы хотите использовать локальный файловый API (зачем?), Databricks устанавливает его по умолчанию на /dbfs.

Поскольку вы вызываете ADD PARTITIONS без местоположения, он использует корневой путь для таблицы (dbfs:/user/hive/warehouse/foo_test на основе вывода DESCRIBE), поэтому, если вы решили использовать локальный API и использовать конфигурацию по умолчанию, вы должны написать

/dbfs/user/hive/warehouse/foo_test/datestamp=20180102

Если вы используете нестандартную конфигурацию, было бы здорово, если бы вы включили ее в свой вопрос.

...