Athenaのmigrationやpartitionするathena-adminを作った

(2017-12-24)

https://github.com/sambaiz/athena-admin

AthenaはS3をデータソースとするマネージドなデータ分析基盤。Prestoベースで標準SQLを実行できる。

料金はスキャンしたデータ量にかかり、$5/TB。1MB切り上げで、10MB以下のクエリは10MBになる。 データ量に対してかなり安く使えるものの、フルスキャンしてしまうとBigQueryと同様にお金が溶けてしまうので、大抵はパーティションを切ることになるのだけど都度locationを指定してADD PARTITIONを実行するのは大変。さらにスキーマを変更するのにもALTER TABLE ADD COLUMNSなどはないのでテーブルを作り直すことになるが、当然パーティションも全部作り直すことになる。

ではどうしようもないかというとMSCK REPAIR TABLEというのがあって、 これはS3のObjectのdt=YYYY-MM-DDのようなkey=valueのprefixを認識してパーティションを作るもの。作り直す際もこれ1クエリで終わる。それなら最初からそういう風に置けばよいのではというところだけど、勝手にYYYY/MM/DD/HHのprefixを付けてしまうFirehoseのようなのもある。

今回作ったathena-adminは以下のような定義ファイルから、 パーティションのkey=valueのprefixが付くように置き換えたり、変更があったらmigrationする。 このファイルを書き換えるだけで基本的にどうにかなるし、バージョン管理すればテーブル定義の変更を追うことができる。

{
  "general": {
    "athenaRegion": "ap-northeast-1",
    "databaseName": "aaaa",
    "saveDefinitionLocation": "s3://saveDefinitionBucket/aaaa.json"
  },
  "tables": {
    "sample_data": {
      "columns": {
        "user_id": "int",
        "value": {
          "score": "int",
          "category": "string"
        } /* "struct<score:int,category:string>" のように書くこともできる */
      },
      "srcLocation": "s3://src/location/",
      "partition": {
        "prePartitionLocation": "s3://pre/partition/", /* optional */
        "regexp": "(\\d{4})/(\\d{2})/(\\d{2})/", /* optional */
        "keys": [
          {
            "name": "dt",
            "type": "string",
            "format": "{1}-{2}-{3}", /* optional */
          }
        ]
      }
    }
  }
}

使い方はこんな感じ。使い方によってはmigrate()だけ呼ぶこともあると思う。 replaceObjects()にはmatchedHandlerというのを渡すこともできて、 UTCからJSTに変換するといったこともできる。

$ npm install athena-admin
const AthenaAdmin = require('athena-admin').AthenaAdmin;
const dbDef = require('./sampledatabase.json');
const admin = new AthenaAdmin(dbDef);
await admin.replaceObjects();
await admin.migrate();
await admin.partition();