UUUM攻殻機動隊(エンジニアブログ)

UUUMのエンジニアによる技術ブログです

LEGOブロックで スクラム入門勉強会

10月25日(金)にワイクル株式会社の角 征典様( @kdmsnr )をお招きし、LEGOブロックでスクラム入門の勉強会を行いました。
弊社ではスクラム開発しているプロダクトとそうでいないプロダクト双方あり、私が担当しているプロダクトではスクラムを導入していなかったため、いろいろ発見のある勉強会でした。

第1部:スクラムの歴史〜基礎の説明

第1部ではアジャイル開発の歴史から始まり、現在の複雑化したシステム開発の実態、スクラム開発とはどういったものなのか、わかり易く説明がありました。
その中でアジャイルとは傘に喩えられるように骨組みであり、特に中身は無いものであると言うこと。それを補完すために様々な開発手法が存在し、スクラムもその中の一種であると説明がありました。
また、スクラムをすることでチーム内の知識・経験を蓄積することができ、より強固なチームへ進化させていくものだということがわかりました。

第2部:LEGOで街づくりをしながらスクラム体験

座学終了後、レゴを使用してのスクラム開発の体験です!
この勉強会では開発側・顧客側を体験できるように設計してあるため、自分たちが設計した街を他チームが、他チームが設計した街を自分たちが作っていきます。

まず各チームが家族という設定で欲しい建造物をカードに書き出していき、模造紙を使い理想の街の設計図を作っていきます。
設計図作りが終わったらカード毎に優先度をつけて並び替えていきます。その後、開発者として他のチームへ移動します。

f:id:a-hiro35:20191031172047j:plain
私達チームの街は商店街は駅近に、公共施設は自然の近くに配置しました。

f:id:a-hiro35:20191031172015j:plain
他のチームのイラストレベルが高すぎてびっくりしたり。。。

移動したら、他チームの設計図を元に、①見積もり、②スプリント、③レビュー・振返りを繰りを繰り返して街を完成させていきます。

まずはプランニングポーカーでざっくりと工数見積もりをします。見積もる際に出てきた疑問点は相手チームのプロダクトオーナーに相談して進めていきます。
その後、3回のスプリントで全てを完成できるように、Velocityを算出。
予想値ピッタリになるように、プロダクトバックログの上から順番に実現できそうなころまでストーリーを引き、開発していきます。

1回目のスプリントでは顧客の要望をきちんと把握できておらず、顧客の望む通りの建物をうまく作り上げることができない人が出てきました(私です)。
その結果、Velocityの予想値をかなり下回り、不本意な結果に終わってしまいました。

2回目のスプリントでは1回目の振り返りを基に再見積もりをし、新たにVelocityを設定していきます。
前回の反省を踏まえ、工数が大きなものは複数人で開発するように変更しました。

f:id:a-hiro35:20191031171729j:plain

前回中途半端に終ってしまったモノは顧客が求める建物としての要素を追加していき、また工数が大きいモノも複数人で開発することで時間内に完成することができました。
顧客レビューでは全ての建物に対して合格をいただき、予想値通りの開発をおこなうことができました。

f:id:a-hiro35:20191031172115j:plain

f:id:a-hiro35:20191031171817j:plain
最後に、チームで作成した傑作の油田です。

まとめ

勉強会を終えて、1回目ではバラバラだったチームに一体感が生まれるのを感じ、開発スピードも上がっているのを実感することができました。
また、顧客の要望を適切に理解する必要性、どう叶えるかをチームで考えることで一体感が生まれたのを感じました。
メリットを多く感じたので、自分のチームでもスクラム開発をしたい!と思える会でした!

Docker + MeCab + JupyterLabによる分析環境の構築

こんにちは、分析チームの門脇です。

日頃クリエイターに関するデータ分析業務を行う際、環境ごとのライブラリの管理が面倒だったり、形態素解析エンジンの導入、notebookの設定をやり直す必要があるなど何かと不便でした。

そこで今回は、Dockerを利用して、簡単にクリエイター分析環境を構築してみました。

Dockerについて

Dockerはコンテナ型の仮想化環境のことで、Dockerfileに仮想環境に取り入れたいものの処理を記述することで、簡単に同一環境を再現でき、環境ごとに設定をやり直さなくて済むといったメリットがあります。

Dockerによる環境構築ついて詳しく知りたい方はこちらにわかりやすくまとめられています。

今回は記事の中でも紹介されているKaggleが提供しているDockerイメージをベースにDokerfileを作成していきます。

MeCabについて

クリエイターについて分析を行う際に、テキストデータを単語ごとに分割して関連ワードを取得したいことがあります。

MeCabは日本語の形態素解析エンジンの中では最もよく使用されていて、mecab-ipadic-NEologdというシステム辞書があり、新語・固有表現に強い単語を分割する際に有効です。

例として、『 ブンブンハローYouTube、どうもヒカキンです!』を調べてみます。

  • MeCab標準辞書のとき f:id:guajfv:20191017141259p:plain

『ブンブンハローYouTube』について

  • ブンブン
  • ハロー
  • YouTube

それぞれ別の単語として認識されてしまいます。

  • mecab-ipadic-NEologdのとき f:id:guajfv:20191017141223p:plain

『ブンブンハローYouTube』として固有名詞として分割でき、『ヒカキン』も固有名詞として認識されます。

日々新しい用語が生まれるYouTubeにおいて、mecab-ipadic-NEologdを使うことで、簡単に対応することができます。

JupyterLabについて

みんな大好き『Jupyter notebook』の後継機のIDEで、オープンソースとして公開されています。

『Jupyter notebook』をより使いやすくしたものであり、こちらで便利機能が詳しく紹介されています。また、自分好みに拡張機能を追加することができ、作業効率を上げることができます。実際にDockerfileへ拡張機能の導入を取り入れてみました。

作成したDockerfile + docker-compose.yml

Dockerfile

# Kaggleが提供しているDockerイメージをベース
FROM gcr.io/kaggle-images/python:v67


RUN pip install -U pip && \
    pip install fastprogress japanize-matplotlib

# mecabとmecab-ipadic-NEologdの導入
RUN apt-get update \
    && apt-get install -y mecab \
    && apt-get install -y libmecab-dev \
    && apt-get install -y mecab-ipadic-utf8 \
    && apt-get install -y git \
    && apt-get install -y make \
    && apt-get install -y curl \
    && apt-get install -y xz-utils \
    && apt-get install -y file \
    && apt-get install -y sudo


RUN git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git \
    && cd mecab-ipadic-neologd \
    && bin/install-mecab-ipadic-neologd -n -y

RUN pip install mecab-python3

# nodejsの導入
RUN curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - \
    && sudo apt-get install -y nodejs

## JupyterLabの拡張機能

# 変数や行列の中身を確認
RUN jupyter labextension install @lckr/jupyterlab_variableinspector

# 自動整形
RUN pip install autopep8 \
    && pip install jupyterlab_code_formatter \
    && jupyter labextension install @ryantam626/jupyterlab_code_formatter \
    && jupyter serverextension enable --py jupyterlab_code_formatter
  • Kaggleが提供しているDockerイメージは最新のものを指定しています。(2019/10/17時点)
    また、こちらから適宜最新のイメージを確認していただければと思います。

  • mecab-ipadic-NEologdのインストールはこちらに記載されているライブラリを入れます。また、PythonからMeCabを使用するために mecab-python3もインストールします。

  • JupyterLabの拡張機能の利用についてはNode.jsが必要となるのでインストールします。また、今回は個人的に便利だと思ったものを拡張機能としてインストールしています。

docker-compose.yml

version: "3"
services:
  jupyterlab:
    build: .
    volumes:
      - $PWD:/content
    working_dir: /content
    ports:
      - 8888:8888
    command: jupyter lab --ip=0.0.0.0 --allow-root --no-browser

ここでは、コンテナ起動時にjupyter labが起動するよう設定しています。

下記コマンドで、コンテナを作成して、起動します。--buildを指定することで事前にイメージを作成してくれます。

$ docker-compose up --build

するとコンソール上に結果が表示されます。

jupyterlab_1  |     Copy/paste this URL into your browser when you connect for the first time,
jupyterlab_1  |     to login with a token:
jupyterlab_1  |         http://7147a0639219:8888/?token=××××××××××××××

あとはホスト名をlocalhostにして、ブラウザでログインするだけです。

  • MeCabをPythonで使うとき
    • 辞書のインストール先はJupyterLab上で下記コマンドにより確認できます。
      !echo `mecab-config --dicdir`"/mecab-ipadic-neologd"
    • 今回は、/usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologdにインストールされたことが確認できたのでコードを書く際は、インストール先を指定します。
import MeCab

tagger = MeCab.Tagger(
    '-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd'
)
print(tagger.parse('ブンブンハローYouTube、どうもヒカキンです!'))

すると、先ほど示した例のようなmecab-ipadic-NEologdを使用したときの結果が出力されます。

まとめ

Dockerを利用することで自分好みの分析環境をサクッと作れちゃいます。環境構築という煩わしいことに時間をかけずに分析に集中できるのでとってもオススメです!

みなさんも自分好みの環境を作成してみてはいかがでしょうか!!!

参考文献

UUUM System Meetup #1

f:id:chibiProgrammer:20190919015916j:plain こんにちは、エンジニアの中村です。

9月6日にUUUM System Meet Upを開催したので、 その様子を書いてみました。

uuum.connpass.com

今回は約30人以上もの人がイベントに参加してくださいました。

攻殻機動隊の初イベントにも関わらず

たくさん集まってくださって嬉しかったです!

今回のイベントは、UUUMを支えるテクノロジーや

普段から学んでいることをアウトプットし、

社内外の技術者たちと交流を深めたい!という目的の元開催いたしました。

イベントの発表内容はこんな感じです。 今回は発表者を何人かピックアップしてご紹介したいと思います。

発表内容

発表者 役職 タイトル
nakatsuka_d マネージャー UUUM満開~なんで私が登壇に!?~
myaunraitau エンジニア プラットフォームのデータを解析するお話
sabomasa エンジニア 再生回数のデータを予測するお話
btomasato CTO ぼくのかんがえたさいきょうの GAS かいはつかんきょう
killyishuguro PM デザイン思考と初心者PM
MaxYasuda エンジニア インフラ勉強初めて1ヶ月なのでECS FARGATEでrails構築した

まず最初はnakatsuka_dさんの「UUUM満開~なんで私が登壇に!?~ 」

f:id:chibiProgrammer:20190917193124j:plain
UUUM満開~なんで私が登壇に!?~

オタサーの姫を作ると営業と仲良くなれるという話や、UUUMのことを面白おかしく紹介してくださったりと、会場もとても盛り上がりました。

次はmyaunraitauさんの「プラットフォームのデータを解析するお話」

f:id:chibiProgrammer:20190918112052j:plain
プラットフォームのデータを解析するお話

機械学習を用いてクリエイター間の類似度算出を行うという発表でした。

機械学習をあまり知らない私でも雰囲気を掴めるようなわかりやすいスライドで、機械学習って色んなことに使えるんだなぁという気付きにもなり、とても楽しかったです。

次はsabomasaさんの「再生回数のデータを予測するお話」

f:id:chibiProgrammer:20190918112048j:plain
再生回数のデータを予測するお話

sabomasaさんもmyaunraitauさんに続いて、機械学習を用いたデータ解析の発表でした。

内容は機械学習を用いてYouTubeの再生回数を予測するという感じでした。 再生回数を予測することが出来るなんてびっくりしたし、機械学習やってみたくなりました笑

次に我らがCTO、BTOさんの「ぼくのかんがえたさいきょうの GAS かいはつかんきょう」

f:id:chibiProgrammer:20190919013324j:plain
ぼくのかんがえたさいきょうの GAS かいはつかんきょう

今UUUMに入って業務改善でGASを使っていますが、いつも自分がやっていることよりもっと踏み込んだ話で 私もGASマスターしたいと切実に思いました!

懇談会はピザを囲んでわいわい技術の話などで盛り上がりました。 UUUM以外のエンジニアやPM、デザイナーの方とお話ができて本当に楽しかったです。

f:id:chibiProgrammer:20190919014511j:plain
懇談会の様子

f:id:chibiProgrammer:20190917192721j:plain
全体写真

とても楽しいイベントとなり、本当に良かったです。 イベントに参加して下さった皆様本当にありがとうございました!

第2回も12月頃に行いますので、是非遊びにきてください!

秋の開発合宿を開催しました!

f:id:c14043:20190930155209j:plain

こんにちは!今回開発合宿のブログ担当する、インターンの鷲見です!

システムユニットでは年2回、開発合宿を行なっています。

今回行なった場所は湯川原にある「おんやど恵」という旅館です。開発合宿(旅行)ではよくお世話になっているのでところです。

  • 都内から二時間ほどで行ける
  • 開発合宿用のプランがある
  • 24時間使える会議室がある
  • Wi-fi環境が整っている
  • 温泉と足湯

といった環境がおんやど恵は整っているので、開発合宿をするのにとても便利です。

www.onyadomegumi.co.jp

旅館紹介

実際にどんな旅館なのか紹介していきます!

会議室

こちらが会議室です。一人、一人スペースが用意されているので、場所に困ることはありません。また成果発表用にプロジェクターも用意してもらいました!

f:id:c14043:20190930122526j:plain

温泉

温泉は夜、早朝といつでも入ることができるので最高ですね!

f:id:c14043:20190930122402j:plain

中庭には足湯があり、入りながら開発もできるのでとても快適です!

f:id:c14043:20190930122103j:plain

食事

食事はコースで出てきます。味もボリュームも十分あるので大満足です。

f:id:c14043:20190930123726j:plain

このお肉と味噌組み合わせはとても美味でした!

f:id:c14043:20190930123737j:plain

開発は何をしたのか?

今回の開発合宿はテーマは「自由開発」です。

日頃業務ではやらないことに挑戦したり、技術をより理解すること、PMの方達はチームが力を最大限発揮するための研究にたくさんの時間を使うことができました。

f:id:c14043:20190930125118j:plain

お昼の2時ごろから着々と取り掛かっていきます。

深夜の追い込み

食事をした後、会議室組は深夜の追い込みをかけてきます。

f:id:c14043:20190930125905j:plain

支給品も届き、仕上げに取り掛かっていきます。

f:id:c14043:20190930143758j:plain

翌朝

朝に少し作業した後、成果発表を順番にしていきます。中には徹夜して限界を迎えてしまう人も。。。

f:id:c14043:20190930154959j:plain

皆さん短い時間の中で高い成果を上げていました。。。

日頃の業務外の技術を使って作られた作品が多かったので、発表はとても面白いものとなりました。

f:id:c14043:20190930160150j:plain

まとめ

2日間に渡り開発に集中できる素晴らしい環境を整えてくださったおんやど恵の皆様ありがとうございました。

すばらしい環境だからこそ、短い時間の中でもそれぞれ成果を出すことができました。

開発と発表を通して、それぞれ知識を共有できたのでとても有意義な時間を過ごせてよかったです。

最後は集合写真終わろうと思います。

f:id:c14043:20190930160745j:plain

Athena + Glue + (Terraform)でいい感じにファイル上のデータを集計しよう

システムユニットのt_u_a_kです。ブログ登場は初めてです。私は業務で少々大きめのデータの集計ということをやっていますが、その際にはAWSのAthenaとGlueを試しました。手軽でよかったので紹介します。

AthenaとGlueについて

まずAthenaについてですが、これはS3上のデータに対するクエリサービスです。データベースに対するクエリサービスではなく、S3上のテキストファイル(もしくはそれらを圧縮したりしたもの)に対してデータ構造を定義し、いわゆるSQLを使って普通にクエリが書けます。この時点でAthenaのようなサービスや仕組みに触れたことがない人にとっては「は?」って感じですね。AthenaはPrestoというFacebookが開発したクエリエンジンを使っていて、大きなデータでも爆速で結果が返ってきます。Presto公式ではFacebook自身が300PB以上のデータの分析に利用していると書いています。ここまで来るとでかすぎて想像もつきませんが、通常の利用であれば本当に驚くほどのスピードでクエリの結果が返ってきます。

aws.amazon.com

次にGlueです。GlueはいわゆるETLサービスというやつです。最近だとデータウェアハウスを構築するところも多いと思いますが、いろんなところにいろんな形で存在しているデータを変換したり移動させたりいい感じに集めるときに使うサービスというのが非常に雑な説明です。Glueにはデータカタログという機能があり、これがAthenaと一緒に使える機能です。Athenaはクエリサービスと書きましたが、Glueで定義したデータカタログをいわゆるデータベースやテーブルと見てクエリをすることができます。これではわかりにくいと思うので下で説明していきます。

aws.amazon.com

今回使うデータ

例えばこんなデータがあったとします。

# hikakin.csv
video_id,title,channel_id,views,date
zW4HJkuFFtc,【ランキング】ヒカキンがガチでウマいと思うセブンの商品トップ3!【2019年5月編】,UCZf__ehlCEBPop-_sldpBUQ,1826863,20190518
VY0EXQqSeRc,顔面が大変なことになりました…,UCZf__ehlCEBPop-_sldpBUQ,1650048,20190517
MgeD8MB6fyg,金属アレルギー検査したらまさかの結果が…【1900万円の時計のその後】,UCZf__ehlCEBPop-_sldpBUQ,1906878,20190515

皆様ご存知のヒカキンさんのチャンネルHikakinTVの動画について、2019年5月のある時点でのデータです。1行目が動画IDや動画タイトルといったヘッダー、2行目以降がデータになっています。他にもこのような似たデータを用意しました。0214mexはじめしゃちょーさんでtsuriyoka釣りよかでしょうさんの動画に関するデータです。釣りよかでしょうさんに関してはサブチャンネルのデータも混ざっています。これらがそれぞれhikakin.csvhajime.csvtsuriyoka.csvという名前で存在している、もっというとUUUM所属の各チャンネルごとにこのようなデータがあると仮定して、Athenaでクエリをかける準備をしていきます。 (※0214mexなどを見ても何のこと?と思う方もいらっしゃるかもしれませんが、はじめしゃちょーさんのYouTubeチャンネルについてはhttps://www.youtube.com/user/0214mexというURLでもアクセスできるようになっており、他のチャンネルでもこれに似た形でURLが表記されることがあります。)

# 0214mex.csv
video_id,title,channel_id,views,date
dmpYE9u3cr4,"【50,000枚】3年間集めた遊戯王カード全部売ったら金持ちになったwwwww",UCgMPP6RRjktV7krOfyUewqw,1280160,20190520
xUFNcNQ24Ho,家に隠されたドラゴンボールがガチで見つからない件。,UCgMPP6RRjktV7krOfyUewqw,1055697,20190519
STA6C9ftvmw,コンビニ弁当をミキサーでドロドロにしても味が分かる説,UCgMPP6RRjktV7krOfyUewqw,969160,20190517
# tsuriyoka.csv
video_id,title,channel_id,views,date
d0XrWwauyQY,むねお船は初心者に優しいらしい,UC4QadOSsJu54Qs8z99shRiQ,136100,20190521
dwXSckt1lM4,庭でイカを料理してたら変なの来た,UC4QadOSsJu54Qs8z99shRiQ,215405,20190520
1AuvYVUMNGs,リフォームした家の壁に缶スプレーでらくがきしてみた!,UCD7-Ocp4InwPKzwiq_U-Abg,230155,20190519
ew0HdXG3SKQ,ドラム缶でオリジナルBBQコンロを作る!,UCD7-Ocp4InwPKzwiq_U-Abg,168260,20190521
j5aQ_Y3_I_U,新居キッチンの紹介します!,UCRT-74ovdMKOFBC96w_gfyQ,105864,20190521
YC1OnPK2fWE,ミルフィーユカツで新潟のB級グルメ作ってみた!,UCRT-74ovdMKOFBC96w_gfyQ,73117,20190520

S3へのデータの保存

AthenaはS3上のデータに対するクエリサービスなので、まずはデータをS3に置かなければいけません。今回は

  • 2019年5月のデータ
  • チャンネルごとに別ファイル

となっているので、仮にデータが増えるとすれば別の月のデータだったり、違うチャンネルでファイルが作られるということが考えられます。このような場合にはS3に保存する際に

  • s3://my-bucket/year=2019/month=5/channel=hikakintv/hikakin.csv
  • s3://my-bucket/year=2019/month=5/channel=0214mex/hajime.csv
  • s3://my-bucket/year=2019/month=5/channel=tsuriyoka/tsuriyoka.csv

というふうに/key=value/のパーティションを作ってあげることで、Athenaでクエリをかける際にまるでyearchannelといったカラムがあるようにクエリをすることができます。channelのカラムが1チャンネル1つに対応していないじゃないかとかchannelキーに対するvalueのルールがおかしいんじゃないかといった意見もあるかと思いますが、今回tsuriyoka.csvに複数チャンネルのデータが入ってしまっているため、ファイルの中を見る前はパーティションを厳密にチャンネル単位で分割することができません。パーティションについては細かくすればするほどクエリの条件を細かく設定できるので料金面で有利になる一方、ファイルをS3に設置するコストが高くなってしまうなどもあるので、どの程度の粒度で分析や集計を行いたいかによってパーティション設計は考えていくべきだと思います。自動的にS3にファイルが流れてくるような状況から作るのであれば、パーティション設計はますます重要です。

docs.aws.amazon.com

データ構造を定義する

今回のデータを見たときに、どういうクエリがかけるでしょうか。(本来はどういうことを知りたいかが先に来るべきですが今回はちょっと置いておきます。) 例えば、

select sum(views) as total_views
from s3上のデータ
where year = 2019 and month = 5 
and channel in ('hikakintv`, 'mex0214`)

とか

select videoid, views
from s3上のデータ
where year = 2019 and month = 5 
order by views desc
limit 5

などがあるでしょうか。別の年月やチャンネルが増えればもっといろんなパターンが出てくるとは思いますが、共通しているのはs3上のデータをテーブルとして、CSVの各カラムやパーティションをselect文に入れたいということです。これをやるためのデータ構造をGlueで定義してみましょう。

Glueでデータカタログを定義する

AthenaでクエリをするためにGlueでデータカタログを定義しますが、データカタログを定義するとはデータベースとテーブル(およびその中のカラム)を定義することです。Glueにおけるデータベースとはいろんな場所にあるデータを統一的に扱うためのメタデータストアになりますが、データベースが必ずどこかのバケットと紐づくなどは無いので、実際あまり意識する必要はありません。必要に応じて作っておけばいいものになります。今回作成したデータベースについても名前以外は何も決めていない状態です。

f:id:xxuxa_k:20190928063135p:plain

次はテーブルです。今回のようにAthenaでのクエリを目的としたテーブル作成においては、テーブルとバケットが1:1だと思っておくのがよいと思います。テーブルに指定する内容は大きくわけてスキーマとそれ以外のオプションになります。オプションの項目としてはどのようにデータを解釈させるかを決めるHadoopのフォーマットなどがあります。かなり細かく指定できるようですが、私もすべては把握できていません。いろんな形式のデータを使ってみたりすることでだんだんわかるようになってくるのだと思います。今回作ってみたblog_test_tableは以下のようなデータカタログ設定になっています。

f:id:xxuxa_k:20190929052618p:plain

f:id:xxuxa_k:20190928063532p:plain

Terraformの利用

↑の画像に出したデータカタログの内容をAWSコンソール上から設定することは可能です。しかし、設定の初期などはパーティションを変えることがあったり、なぜかAthena側でデータカタログのロードにうまくいかなかったりと、最初から作り直したほうがいろいろと楽な場合が多いです。(個人的にはHadoopだったり分散処理に関する知識が足りないと十分にエラー調査していくことが難しいのかなと思っています。) 作り直すたびにAWSコンソール上でポチポチやっていたこともあったのですがつらすぎるので、データカタログはTerraform化してしまいましょう。テーブルの追加も作り直しもterraform apply一撃で済むようになることでかなり作業が楽になるのと、クエリを書いて調査・分析をするという本質的な作業に時間を割くことができるようになります。もちろんTerraformの代わりにCloud Formationもありだと思います。 データカタログ部分のterraformコードはこのような感じです。もともとはv0.11系で動くように書いていたのですが、今回ブログを書くにあたってv0.12.9で動作するように書き換えました。(terraform 0.12updateコマンドがあるので基本的には自動で書き換えてくれましたが、一部自分で直すような感じになりました。) ポイントとしてはstorage_descriptor.ser_de_infoかなと思います。S3に保存してあるファイルの形式によってここが変わってきます。今回はCSVを使っていますが、TSV、JSON、Hadoop形式などにも対応していて、形式に合わせてSerDeというシリアライズ/デシリアライズライブラリにオプションを与えることになります。

locals {
  blog_database_name   = "test_catalog_db"
  blog_bucket_location = "s3://xxx/yyyy/..../"
}

resource "aws_glue_catalog_database" "test_catalog_db" {
  name         = local.blog_database_name
  description  = ""
  location_uri = ""
  parameters   = {}
}

resource "aws_glue_catalog_table" "blog_test_table" {
  name          = "blog_test_table"
  description   = ""
  database_name = local.blog_database_name

  table_type = "EXTERNAL_TABLE"

  parameters = {
    EXTERNAL                 = "TRUE"
    has_encrypted_data       = "false"
    classification           = "csv"
    "skip.header.line.count" = "1"
  }

  partition_keys {
    name    = "year"
    type    = "int"
    comment = ""
  }
  partition_keys {
    name    = "month"
    type    = "int"
    comment = ""
  }
  partition_keys {
    name    = "channel"
    type    = "string"
    comment = ""
  }

  storage_descriptor {
    input_format  = "org.apache.hadoop.mapred.TextInputFormat"
    location      = local.blog_bucket_location
    output_format = "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat"

    ser_de_info {
      name                  = "blog_test_ser_de"
      serialization_library = "org.apache.hadoop.hive.serde2.OpenCSVSerde"

      parameters = {
        quoteChar     = "\""
        separatorChar = ","
      }
    }

    columns {
      name    = "video_id"
      type    = "string"
      comment = ""
    }
    columns {
      name    = "title"
      type    = "string"
      comment = ""
    }
    columns {
      name    = "channel_id"
      type    = "string"
      comment = ""
    }
    columns {
      name    = "views"
      type    = "int"
      comment = ""
    }
    columns {
      name    = "date"
      type    = "string"
      comment = ""
    }
  }
}

データカタログ部分についてはこれだけです。CSVの形式の変更などがあったときもコード変更とterraformの適用だけです。S3バケットもterraform化できていればより完璧です。 docs.aws.amazon.com

Athenaでクエリする

あとはAthenaでクエリをするだけです。AWS CLIからだと結構柔軟に設定できますが、今回はAthenaのコンソール上からやります。忘れてはいけないことですが、S3にデータを追加したら、MSCK REPAIR TABLE test_catalog_db.blog_test_table;というSQLを流しておきましょう。これをやらないとAthenaが新たに追加されたファイルを認識できなくなります。

f:id:xxuxa_k:20190928065421p:plain

select * from blog_test_tableをしてみると、3.22秒と出ました。仮にこれがRDSであればどう考えても遅すぎますが、Athenaはあまりに小さいデータに対してはRDBMSよりもパフォーマンスが悪くなります。逆に大きいデータに対してはとんでもないスピードで結果を返してきます。今回についてはクエリを投げられるようになることが目的なのでここまでにしておきますが、実際にやったことはバケットとデータカタログの設定だけなのでかなり簡単にCSVのようなデータに対してもクエリが投げられることがわかったと思います。もちろん形式はCSVだけでなく、多様な形式をサポートしています。

f:id:xxuxa_k:20190928080139p:plain

料金について

Athenaはスキャンしたデータに対する従量課金のため、スキャンデータを減らすことが利用料金を減らす一番の近道です。同時にスキャンデータを減らすことは処理速度を上げることにもつながります。 データは圧縮形式でも扱えるため圧縮してS3に入れる、Parquetなどの列形式へ変換するなどの方法も役に立つと思います。

まとめ

AthenaとGlueのデータ集計での利用について書いてみました。今回ほど小さいファイルであればSQLiteを使うのもありだと思いますが、実際にはそこそこのサイズがあると思うので、ファイル上のデータについて単純なクエリをしたいということだとこれが一番簡単な気がします。AWSマネージドなので管理コストも最小限です。

最後に

やっと1回ブログ書けた、、、。システムユニットでは一緒に働いてくれる方を募集中です。

recruit.uuum.co.jp

Railsプロジェクトを引き継いでから安定させるまでに行ったこと

nazoです。現在は厳密には攻殻機動隊(システムユニット)ではないのですが、開発に関する大きな動きがありましたのでまとめてみたいと思います。

何の話?

LMND というシステムがあるのですが、これの開発を急ピッチで進めたいという事で急遽移動することになり、快適な開発環境になるまでに行ったことについての話になります。

LMNDのサービスの詳細についてはここでは割愛させて頂きますが、システム的にはRails4系にMySQLという、少し古いものの一般的な構成で作られたものになっております。2018年9月に吸収合併を行ったのですが、その際に開発体制が完全内製に切り替わってしまったため、引き継ぎがほとんどない状態から体制が切り替わってしまったという状態になります。社内の開発者が先に割り当てられていたのですが、困っているので助けてくれということで私が途中から入ることになりました。

作り直すかどうか

事前情報では「やばかったら作り直してもいいよ」とは言われたのですが、作り直しというのは一見楽しそうですが難しい問題を多く抱えています。

  • サービスをやり直すわけではないのでデータは既存のまま使えるようにしないといけない
  • 機能が多く、かつそれらが契約上廃棄できるものではない場合、それらを全て同様に移植しなければならない

一方で、それでも作り直さないといけないという場合も存在します。

  • コードの汚さがあまりにどうしようもなく、何をするにもほぼスクラッチで開発するしかないような状態
  • フレームワークなどが一般的ではないまたは独自のもので、今後のアップデートに対応することがほぼ不可能な状態
  • 予算が十分にあり、かつ作り直しのビジョンが明確にある場合

ただし予算があるケースの場合以外は、最終的には全て作り直すとしても一部分から作り直すとか新しいものと古いものを共存できるようにするとか、様々な手法があると思います。規模の大きなアプリケーションの場合、そのアプリケーションが解決しようとしているもの(事業)が何かを適切に見極め、交通整理を行うことでどこをどう作り直すべきなのかが見えてくると思います。

今回のプロジェクトはRails製で、コードが読みにくい箇所が多いもののRailsそのものを魔改造しているというわけでもなく、作りながら書き直すことが十分に可能なレベルでしたので、基本的には作り直さないという方針を採ることにしました。

続きを読む

polidogさんをお招きして社内勉強会をしました

こんにちは、今年新卒で入社したエンジニアの中村です。

6月28日(金)にパーティーハード株式会社のpolidogさん(@polidog)をUUUMにお招きし、Symfony使いの為の勉強会を行いました!!

4月からSymfonyを使い始め、苦しんでいた私にとってもすごく有意義な時間となりました。

f:id:chibiProgrammer:20190702114021j:plain
写真右奥がpolidogさんです

Symfonyとは、Webアプリケーションフレームワークで、 弊社ではクリエイターポータルサイト「CREAS」の開発にSymfonyを使っています。 普段の開発では柔軟なSymfonyアプリケーションを作ろうと意識しても、 実際どう設計すればいいのか分からないことが多く、今回の勉強会で意識するべきところを教えて頂きました。

以下勉強会の資料になります。

speakerdeck.com

弊社のエンジニアもSymfonyに興味がある人が多く、勉強会の後の質疑応答では沢山質問にお答えしていただきました。 以下、質疑応答で出た内容になります!

  • SymfonyのJob Queue はないのか?

    - BCCResqueBundle
    - JMSJobQueueBundle
    
  • Security.ymlが解決されるタイミングは?

  • Security.bundleってcomposerとかじゃなくてSymfonyで提供されているのか?

    - composerである。Symfonyのコアチームが提供している。
    
  • 1コントローラーつき1メソッド(コンストラクタを除く)とした場合、CRUD等の機能はどのように分けているか?

    - ディレクトリで切っていって、名前空間で分けている。
    

今回の勉強会でリファクタを強く意識しましたが、polidogさん曰く 頑張ってリファクタしすぎるのは良くない、動いているコードが最終的には正解だと思っているが、 変化させるタイミングの時にちょっとづつ綺麗にしていくのが大事とのことだったので、 日頃から少しづつ意識して今あるコードを綺麗にしていきたいなと思いました。

今回はSymfonyについて色々知ることができ、とても楽しい会となりました!

polidogさん、お忙しい中お越しいただきありがとうございました!

www.wantedly.com