Раздел Athena запрос по дате создания S3 - PullRequest
0 голосов
/ 08 марта 2019

У меня есть корзина S3 с ~ 70 миллионами JSON (~ 15 ТБ) и таблица athena для запроса по метке времени и некоторые другие ключи, определенные в JSON.

Гарантируется, что метка времени в JSONболее или менее равна S3-createDate в JSON (или, по крайней мере, достаточно для цели моего запроса)

Можно ли как-то улучшить производительность запросов (и стоимость), добавив в качестве createdate что-то вроде«раздел», который, как я понимаю, представляется возможным только для префиксов / папок?

edit: в настоящее время я имитирую это с помощью CSV-файла S3 для предварительной фильтрации с помощью createDate, а затем загружаю все JSON и выполняюОстальная часть фильтрации, но я бы хотел сделать это полностью внутри Афины, если это возможно

1 Ответ

2 голосов
/ 08 марта 2019

Нет способа заставить Афину использовать такие вещи, как метаданные объекта S3, для планирования запросов.Единственный способ заставить Афину пропускать чтение объектов - это организовать объекты таким образом, чтобы можно было создать секционированную таблицу, а затем запросить фильтры по ключам секционирования.

Похоже, у вас естьИдея о том, как работает разбиение в Афине , и я предполагаю, что есть причина, по которой вы не используете его.Тем не менее, в интересах других людей, сталкивающихся с подобными проблемами, сталкивающимися с этим вопросом, я начну с объяснения того, что вы можете сделать, если сможете изменить порядок организации объектов.В конце я приведу альтернативное предложение, возможно, вы захотите сразу перейти к нему.

Я бы посоветовал вам организовать объекты JSON с использованием префиксов, которые содержат некоторую часть временных меток объектов.Сколько именно зависит от того, как вы запрашиваете данные.Вы не хотите, чтобы это было слишком зернистым и не слишком грубым.Если сделать его слишком детализированным, Athena будет тратить больше времени на просмотр файлов на S3, слишком грубый - читать слишком много файлов.Если наиболее распространенным периодом времени запросов является месяц, это хорошая детализация, если наиболее распространенным периодом является пара дней, то, вероятно, лучше использовать день.

Например, если день является наилучшей гранулярностью дляВ вашем наборе данных вы можете упорядочить объекты, используя такие ключи:

s3://some-bucket/data/2019-03-07/object0.json
s3://some-bucket/data/2019-03-07/object1.json
s3://some-bucket/data/2019-03-08/object0.json
s3://some-bucket/data/2019-03-08/object1.json
s3://some-bucket/data/2019-03-08/object2.json

Вы также можете использовать схему разбиения в стиле Hive, чего и ожидают другие инструменты, такие как Glue, Spark и Hive, поэтому, если у вас нетпричины, по которым это не может спасти вас в будущем:

s3://some-bucket/data/created_date=2019-03-07/object0.json
s3://some-bucket/data/created_date=2019-03-07/object1.json
s3://some-bucket/data/created_date=2019-03-08/object0.json

Я выбрал здесь имя created_date, я не знаю, какое имя будет подходящим для ваших данных.Вы можете использовать просто date, но не забывайте всегда заключать его в кавычки (и заключать в кавычки по-разному в DML и DDL…), поскольку это зарезервированное слово.

Затем вы создаете секционированную таблицу:

CREATE TABLE my_data (
  column0 string,
  column1 int
)
PARTITIONED BY (created_date date)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' 
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://some-bucket/data/'
TBLPROPERTIES ('has_encrypted_data'='false')

Некоторые руководства скажут вам запустить MSCK REPAIR TABLE, чтобы загрузить разделы для таблицы.Если вы используете разделение в стиле Hive (например, …/created_date=2019-03-08/…), вы можете сделать это, но это займет много времени, и я бы не рекомендовал это делать.Вы можете сделать это намного лучше, добавив разделы вручную, что вы делаете следующим образом:

ALTER TABLE my_data
  ADD PARTITION (created_date = '2019-03-07') LOCATION 's3://some-bucket/data/created_date=2019-03-07/'
  ADD PARTITION (created_date = '2019-03-08') LOCATION 's3://some-bucket/data/created_date=2019-03-08/'

Наконец, когда вы запрашиваете таблицу, обязательно включите столбец created_date, чтобы Афина получилаинформация, необходимая для чтения только тех объектов, которые имеют отношение к запросу:

SELECT COUNT(*)
FROM my_data
WHERE created_date >= DATE '2019-03-07'

Вы можете убедиться, что запрос будет дешевле, наблюдая разницу в данных, отсканированных при изменении, например, created_date >= DATE '2019-03-07'на created_date = DATE '2019-03-07'.


Если вы не можете изменить способ организации объектов на S3, есть плохо документированная функция, которая позволяет создавать многораздельную таблицу, даже когда вы можете 'изменить объекты данных.Что вы делаете, вы создаете те же префиксы, которые я предлагал выше, но вместо перемещения объектов JSON в эту структуру вы помещаете файл с именем symlink.txt в префикс каждого раздела:

s3://some-bucket/data/created_date=2019-03-07/symlink.txt
s3://some-bucket/data/created_date=2019-03-08/symlink.txt

В каждом symlink.txt вы помещаете полный S3 URI файлов, которые вы хотите включить в этот раздел.Например, в первый файл вы можете поместить:

s3://data-bucket/data/object0.json
s3://data-bucket/data/object1.json

и второй файл:

s3://data-bucket/data/object2.json
s3://data-bucket/data/object3.json
s3://data-bucket/data/object4.json

Затем вы создадите таблицу, которая будет очень похожа на таблицу выше, но содно небольшое отличие:

CREATE TABLE my_data (
  column0 string,
  column1 int
)
PARTITIONED BY (created_date date)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' 
STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.SymlinkTextInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://some-bucket/data/'
TBLPROPERTIES ('has_encrypted_data'='false')

Обратите внимание на значение свойства INPUTFORMAT.

Вы добавляете разделы так же, как и для любой многораздельной таблицы:

ALTER TABLE my_data
  ADD PARTITION (created_date = '2019-03-07') LOCATION 's3://some-bucket/data/created_date=2019-03-07/'
  ADD PARTITION (created_date = '2019-03-08') LOCATION 's3://some-bucket/data/created_date=2019-03-08/'

Единственная документация по этой функции, связанная с Афиной, с которой мне приходилось сталкиваться, это документы инвентаризации S3 для интеграции с Афиной .

...