Плохое имя поля Athena AWS и несколько папок с Hive DDL

Я новичок в AWS Athena и пытаюсь запросить несколько сегментов S3, содержащих файлы JSON. Я столкнулся с рядом проблем, на которые нет ответа в документации (к сожалению, их журнал ошибок недостаточно информативен, чтобы попытаться решить его самостоятельно):

  1. Как запросить поле JSON, названное круглыми скобками? Например, у меня есть поле с именем «Емкость (ГБ)», и когда я пытаюсь включить его в оператор CREATE EXTERNAL, я получаю сообщение об ошибке:
   CREATE EXTERNAL TABLE IF NOT EXISTS test-scema.test_table (
  `device`: string,
  `Capacity(GB)`: string)

Ваш запрос содержит следующие ошибки:

СБОЙ: ошибка выполнения, код возврата 1 из org.apache.hadoop.hive.ql.exec.DDLTask. java.lang.IllegalArgumentException: Ошибка:: ожидается в позиции 'Емкость (ГБ): строка>', но '(' найдено.

  1. Мои файлы расположены в подпапках S3 в следующей структуре:

    'location_name / YYYY / MM / DD / appstring /'

и я хочу запросить все даты определенной строки приложения (из многих). есть ли какой-нибудь «подстановочный знак», который я могу использовать для замены пути дат? Что-то вроде этого:

LOCATION 's3://location_name/%/%/%/appstring/'

  1. Должен ли я загружать необработанные данные как есть, используя CREATE EXTERNAL TABLE, и только затем запрашивать их, или я могу добавить несколько встроенных операторов WHERE? В частности, это возможно:
CREATE EXTERNAL TABLE IF NOT EXISTS test_schema.test_table (
  field1:string,
  field2:string
  )

ROW FORMAT SERDE  'org.apache.hive.hcatalog.data.JsonSerDe'
WITH SERDEPROPERTIES (
  'serialization.format' = '1'
) LOCATION 's3://folder/YYYY/MM/DD/appstring'

WHERE field2='value'

Каковы будут результаты с точки зрения выставления счетов? Потому что прямо сейчас я создаю этот оператор CREATE только для повторного использования данных в SQL-запросе.

Спасибо!


person Dimgold    schedule 09.04.2017    source источник


Ответы (1)


1. Поле JSON, названное в скобках

Нет необходимости создавать поле с именем Capacity(GB). Вместо этого создайте поле с другим именем:

CREATE EXTERNAL TABLE test_table (
    device string,
    capacity string
)
ROW FORMAT  serde 'org.apache.hive.hcatalog.data.JsonSerDe'
with serdeproperties ( 'paths'='device,Capacity(GB)')
LOCATION 's3://xxx';

Если вы используете вложенный JSON, вы можете использовать свойство Serde mapping (которое я видел в проблеме с Hive Serde работа с вложенными структурами):

CREATE external TABLE test_table (
   top string,
   inner struct<device:INT,
               capacity:INT>
   )
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
with serdeproperties
(
"mapping.capacity" = "Capacity(GB)"
)
LOCATION 's3://xxx';

Это хорошо работает с вводом:

{ "top" : "123", "inner": { "Capacity(GB)": 12, "device":2}}

2. Подпапки

Вы не можете использовать подстановочный знак в середине пути (s3://location_name/*/*/*/appstring/). Ближайший вариант - использовать секционированные данные, но для этого потребуется другой формат именования ваших каталогов.

3. Создание таблиц

Вы не можете указать операторы WHERE как часть оператора CREATE TABLE.

Если ваша цель - снизить затраты на данные, используйте секционированные данные, чтобы уменьшить количество сканируемых файлов или сохранить их в формате на основе столбцов, таком как Parquet.

Примеры см. В разделе: Анализ данных в S3 с помощью Amazon Athena

person John Rotenstein    schedule 09.04.2017
comment
Это становится более сложным, потому что мой JSON вложен. Например: {device: 213123, custom: {capacity (GB): 8.2, ID: 34242}} Как мне писать пути в этом случае? - person Dimgold; 09.04.2017
comment
Я добавил пример использования вложенного JSON с полем Capacity(GB), который меня хорошо зарекомендовал. - person John Rotenstein; 09.04.2017
comment
Проблема круглых скобок была решена идеально, но проблема с вложенными папками разочаровывает. Кажется, я не могу разбить данные на разделы, поскольку структура моих папок /YYYY/MM/DD/APP/, а не /year=YYYY/month=MM/day=DD/app=APP/. Есть ли способ решить эту проблему автоматически? - person Dimgold; 09.04.2017
comment
Верный. Будут использоваться все подпапки. Если вы хотите разбить на разделы, вам понадобится формат файла. Вы можете указать его на уровень подпапок (например, /YYY/MM/DD), и он будет читать файлы и папки ниже этого уровня, но вы не можете разделить на уровне /*/APP. - person John Rotenstein; 09.04.2017
comment
Как мне правильно разбить его, чтобы такие запросы, как: WHERE app='appid', выполнялись только на нужном разделе? - person Dimgold; 09.04.2017
comment
Вам необходимо иметь структуру каталогов как /app=abc/* или /app=abc/year=2017/month=4/day=7/*. - person John Rotenstein; 10.04.2017
comment
к сожалению, у меня нет контроля над структурой каталогов - person Dimgold; 12.04.2017