AWS Glue Datastore: добавление отдельных файлов в разделы - PullRequest
0 голосов
/ 30 октября 2019

У меня есть разделенная на день структура каталогов s3 s3://userlogs/year=YYYY/month=MM/day=DD/ У меня есть серверы, постоянно заполняющие каталог текущего дня файлами - они добавляют около 6000 файлов каждый день. После добавления каждого файла я хочу обновить таблицу userlogs в хранилище данных Glue, чтобы включить ее.

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

ALTER TABLE userlogs ADD
  PARTITION (year = '2016', month = '01', day = '01) LOCATION 's3://userlogs/year=2016/month=01/day=02/'

Однако каждый раз, когда я запускаю эту команду, я предполагаю, что Glue должен сканировать все потенциально тысячи файлов в этом каталоге.

Что яочень бы понравился какой-нибудь метод / команда, которая бы выполняла следующие действия:

ALTER TABLE userlogs UPDATE
  PARTITION (year = '2016', month = '01', day = '01) ADD FILE's3://userlogs/year=2016/month=01/day=02/todays_file_no_3423.parquet.gz'

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

1 Ответ

1 голос
/ 30 октября 2019

Команда ALTER TABLE ... не сканирует ваши данные в S3 (поэтому это бесплатно). Он просто определяет метаинформацию о ваших данных в каталоге данных AWS Glue, т. Е. Расположение файлов в S3, которые должны быть доступны для поиска по запросам Athena, поэтому для завершения этой команды требуется меньше секунды.

Таким образом, Вам не нужно добавлять файлы по отдельности, если вы определили / создали раздел в glue metastore, который «указывает» на местоположение в S3, где находятся эти файлы. Поэтому после

ALTER TABLE userlogs ADD 
PARTITION (year = '2016', month = '01', day = '01') 
LOCATION 's3://userlogs/year=2016/month=01/day=01/';

Вы можете добавить столько же файлов к s3://userlogs/year=2016/month=01/day=01/, и все их содержимое будет доступно для запроса через Афины.

Дополнительные примечания TL; DR

Не уверен, является ли следующее поведение ALTER TABLE userlogs ADD PARTITION ... таким, каким оно должно быть, но:

  • Он только проверяет, существует ли сегмент S3, но не полный путь S3. Таким образом, следующие операторы DDL будут успешными

    ALTER TABLE userlogs ADD 
    PARTITION (..., day='01')    LOCATION 's3://userlogs/year=2016/month=01/day=01/'
    PARTITION (..., day='wrong') LOCATION 's3://userlogs/year=2016/month=01/day=wrong_path/';
    

    Обычные запросы также будут успешными, но с другими результатами, поскольку нет файлов с неправильным путем

    SELECT COUNT(*) FROM userlogs WHERE day = '01'     -- outputs some value
    SELECT COUNT(*) FROM userlogs WHERE day = 'wrong'  -- outputs 0
    
  • Это неНе проверяйте, есть ли у вас разрешение на это место.

    ALTER TABLE userlogs ADD 
    PARTITION (..., day='01')         LOCATION 's3://userlogs/year=2016/month=01/day=01/'
    PARTITION (..., day='restricted') LOCATION 's3://userlogs/year=2016/month=01/day=restricted/';
    

    Это означает, что может произойти сбой одного раздела в мета-хранилище, который указывает на такое расположение SELECT

    SELECT COUNT(*) FROM userlogs  --  error(s): Access Denied ...
    

    Если вы не исключите его в предложении WHERE:

    SELECT COUNT(*) FROM userlogs WHERE day != 'restricted'
    

    или удалите этот раздел с помощью DROP PARTITION

    ALTER TABLE userlogs DROP PARTITION (..., day='restricted');
    -- Followed by, which will succeed
    SELECT COUNT(*) FROM userlogs
    
  • Значения разделов не должны быть такими же, как в местоположении (это как-то ожидаемо), и отличаютсязначения могут использоваться для указания на одно и то же местоположение в одно и то же время.

    ALTER TABLE userlogs ADD 
    PARTITION (..., day='01')    LOCATION 's3://userlogs/year=2016/month=01/day=01/'
    PARTITION (..., day='first') LOCATION 's3://userlogs/year=2016/month=01/day=01/';
    

    Теперь, если мы запросим с помощью предложения WHERE, мы получим тот же результат.

    SELECT COUNT(*) FROM userlogs WHERE day = '01'   
    SELECT COUNT(*) FROM userlogs WHERE day = 'first'
    

    Предположим, что оба они выдают 10 . Однако, если вы сделаете запрос без предложения WHERE, результат будет 20 , поскольку Афина дважды просканировала одно и то же местоположение.

...