Скопируйте файлы паркета и запросите их у Афины - PullRequest
0 голосов
/ 17 марта 2020

Я использую aws -data-wrangler (https://github.com/awslabs/aws-data-wrangler) для обработки pandas фреймов данных. Как только они обработаны, я экспортирую их в файлы паркета с:

wr.pandas.to_parquet(
    dataframe=my_dataframe,
    description=DESCRIPTION,
    columns_comments=COLUMN_COMMENTS,
    parameters=DATASET_TAGS,
    database=my_database,
    table=f"{table}_{latest_refresh_date}",
    path=f"s3://{bucket_out}/{sub_path}/{latest_refresh_date}/",
    procs_cpu_bound=1,
    partition_cols=["date"],
    mode="overwrite_partitions",
    preserve_index=False,
)

Делая это таким образом, он также создает таблицу Glue. Файлы паркета благополучно живут в корзине S3, и я могу запросить данные у Athena, используя имя таблицы Glue, например:

select * from {table}_{latest_refresh_date}

Теперь, допустим, я получил новые данные. Новые данные должны храниться в новом пути S3: например, s3://{bucket_out}/{sub_path}/{other_refresh_date}/. Я обрабатываю новые данные, как и раньше, но я не хочу повторно обрабатывать старые данные. Поэтому я копирую файлы паркета из старого пути в новый, с простой копией S3. Старые данные не обрабатываются с помощью wr.pandas.to_parquet.

Теперь, когда я хочу запросить данные, хранящиеся в s3://{bucket_out}/{sub_path}/{other_refresh_date}/, я могу получить доступ только к новым данным.

select * from {table}_{other_refresh_date}

Это Кажется, я могу только запросить данные, которые были добавлены в таблицу Glue. Я наивно думал, что Афина будет запрашивать путь S3, но, видимо, он более сложный, чем этот.

Не могли бы вы объяснить мне, почему это происходит, и, возможно, предложить обходной путь? Нужно ли каким-то образом регистрировать старые файлы в новой таблице Athena?

1 Ответ

0 голосов
/ 18 марта 2020

Не зная подробностей того, что Pandas делает под капотом, я подозреваю, что проблема заключается в том, что он создает секционированную таблицу (как предполагает часть команды partition_cols=["date"]). Секционированная таблица не просто имеет одно местоположение, она имеет одно местоположение на раздел.

Это, вероятно, происходит: когда вы создаете первую таблицу, вы получаете данные на S3, выглядящие примерно так: s3://example/table1/date=20200317/file.parquet и секционированная таблица с разделом с местоположением s3://example/table1/date=20200317/. У таблицы тоже может быть местоположение, и оно, вероятно, s3://example/table1/, но в большинстве случаев это бессмысленно - оно ни для чего не используется, просто Glue требует, чтобы у таблиц было местоположение.

Когда вы создаете следующую таблицу вы получаете данные, скажем s3://example/table2/date=20200318/file.parquet, и таблицу с соответствующим разделом. Далее я предполагаю, что вы копируете данные из первой таблицы в s3://example/table2/date=20200317/file.parquet (table1 -> table2 - это разница).

Когда вы запрашиваете новую таблицу, она не будет выглядеть в этой location, потому что это не местоположение, принадлежащее какому-либо из его разделов.

Вы можете исправить это несколькими способами:

  • Возможно, вам вообще не нужно разделение Что произойдет, если вы удалите часть команды partition_cols=["date"]? Вы все еще получаете разделенную таблицу? (проверьте в консоли Glue или запустив SHOW CREATE TABLE tableX в Афинах). С неразделенной таблицей вы можете переместить любые данные, которые вы хотите, в местоположение таблицы, и она будет найдена Афиной.
  • Вместо перемещения данных вы можете добавить раздел из первой таблицы в новую таблицу, выполнить что-то например, в Афине: ALTER TABLE table2 ADD PARTITION ("date" = '20200317') LOCATION 's3://example/table1/date=20200317/'.
  • Вместо этого добавьте раздел к старой таблице или оба. Это не имеет большого значения и зависит от того, какое имя вы хотите использовать при выполнении запросов. Вы также можете иметь таблицу, которую вы настроили вручную, которая является вашей основной таблицей, и обрабатывать таблицы, созданные с помощью Pandas, как временные. Как только Pandas создал данные, вы добавляете их в качестве раздела в основную таблицу и удаляете вновь созданную таблицу. Таким образом, вы можете иметь хорошее имя для своей таблицы и не иметь в имени метки даты.
  • Вы можете скопировать данные, если хотите, чтобы данные были все в одном месте, а затем добавить раздел, как указано выше. .
  • Кто-то, вероятно, предложит скопировать данные, как указано выше, а затем запустить MSCK REPAIR TABLE. Это работает, но будет становиться все медленнее и медленнее, когда вы получаете больше разделов, поэтому это не масштабируемое решение.
...