しょ〜うぃん広場

おもにTech系なブログ、ときどき個人的なブログ

新1分間マネジャー を読んだ

読み終わってから2週間ぐらい経ちますが、新1分間マネジャー――部下を成長させる3つの秘訣 を読んだのでそのまとめです。 (若干記憶が薄れているので、誤ったことを書いていたらすみません)

私はマネジメントをしたことがなく、そこまでガッツリマネジメントもされたことがないのですが、このような人が初めてマネジメントをする立場になった時に、初めに読む本としてすばらしい本だと感じました。

"新" とは

「1分間マネジャー」は1982年に書かれたもので、当時はトップダウン型のリーダーシップが当たり前だったためそれを前提に書かれた内容になっていましたが、「新1分間マネジャー」は2015年に出版されており、現代的な横並びの協調的関係が反映された内容になっています。

満足することでパフォーマンスが上がる

「自分自身に満足している人は満足できる結果を生み出す」という真理が書かれていました。最近1年の仕事振りをふり返ってみても、確かに自分自身に満足している時の方がパフォーマンスが高かったように感じます。例えば、スケジュール通りに開発できていて、自分の開発速度に自信を持てるようになってさらに高速に開発できるとか、新しい技術を身につけられている実感があってさらに新たなことに挑戦したくなる等ですね。
これからは1on1で「あなたは今の自分に満足していますか?」と聞いてみるのも良いかなと思いました。

マネジャーは答えを教えない

マネジャーが意思決定をしてしまうのではなく、部下に自分で意思決定させることが大事だと書かれていました。自ら意思決定することで、"自分で" 成功を掴み取ったという自信になり、そしてその自信が高パフォーマンスに繋がっていくようです。(上で言及した内容ですね)

部下が困っている時には

  • なぜそれが起きていると思う?
  • それを解決する方法は例えば何がある?

というように自分で答えを見つけるための道筋を提供してあげると良さそうです。

1分間マネジメント

マネジャーは複数の部下を持っており、また自分自身のタスクもあるため、マネジメントに多くの時間をかけることはできません。その中でどう効率よく部下のパフォーマンスを上げるのかが大事になります。1分間でマネジメントするために「1分間目標」「1分間称賛」「1分間修正」という3つの秘訣があります。

1分間目標

  • 何をいつまでに行うのか、3~5つ目標を立てる。目標は1分で振り返ることができる量にする。
  • 目標を見えるところに貼っておくことで、部下は毎日自分自身をマネジメントすることができる。
  • 目標がなければピンのないボウリングと一緒で、何を倒したらいいのか分からない。

1分間称賛

  • 最初(初めの1ヶ月)のうちは部下の行動やパフォーマンスを観察し、正しいことを行っていれば称賛する。
  • 逆に問題があった場合には、1分間修正を行う。きちんとフィードバックをするので、最初のうちはぎくしゃくするかもしれないよと事前に伝えておく。
  • (褒め方については後述)

1分間修正

  • 誤った行動をした時に修正を促し、さらに高パフォーマンスで働けるようにする。
  • 事実を検証し、一緒に振り返る。
  • マネジャーがそのミスによって組織がどれぐらい影響を受けるのか説明する。その後部下に考えさせる時間を数秒与える。
  • そのミスは取り返せること、このミスによって信頼が揺るがないことを伝える。
  • 部下の成功を応援していることを伝える。
  • 起こした行動に対してのみ指摘を行い、人間性は肯定しなければいけない。

褒め方

私は子供のころから「すごいね!まぁでもできて当然でしょ〜」という感じであまり褒められることなく育てられたことが影響してか、他人を褒めることがニガテです。笑
本には小さなステップごとに褒めるという方法が書かれていて参考になったため紹介します。

覚えたての段階では最初から100点を求めるのではなく、60点ができたら褒める、80点ができたら褒める、最後に100点ができたら褒めるということが大事です。 例えば、「水をください」と幼子に言わせたいとする時、最初は「みじゅ」と近い音を発しただけで褒めてあげます。そうすることで、この発音は正しそう!ということが理解できます。しばらくしたら「みず」と正しく言えた時だけ水をあげ、次のステップでは「ください」まで付けて言おうね、と教えます。
概ね正しい方法でやっていたらその都度褒めてあげることが大事なようです。

最後に

物語になっていて2,3時間で読める短めの本でしたが、勉強になることが大変多い本でした。 気軽に読めるので、定期的に読み返そうと思っています。

この方法は仕事だけではなく家庭でも使えると書かれていました。
1分間目標の存在を知る前から私も取り入れていて、「一緒に住んでいて相手の気になる部分を3ヶ月で2つ直そう!」といって彼女と一緒に紙に改善目標を書いて壁に貼り、月末にお互いの行動を評価しています。(お互いコレを直そう!と共通認識化するのと、3ヶ月で2つという少数に的を絞って行動を改善するのが肝)
まわりの人にも勧めていますがこれが結構オススメで、問題を目標化しておかないと「また今日も指摘された…」「もうわかってるよ…!!」「4つも5つも一気に言われても困る!!」と喧嘩のもとになりがちですが、重要度の高い問題1つ2つを目標として管理しておくと「最近ちゃんとできてるね〜!」や「これ未だに習慣化できてないけど、どう工夫したら良いかな?」などポジディブなコミュニケーションが増えるような気がしています。 みなさんも是非試してみてください!

スクラム向けの残業時間集計ツールを作りました

先週会社で1on1をやった時に、最近showwinさんのブログ更新されてないですよね…?と言われてしまいました…笑
ということで、今回は最近作ったコマンドラインツールの紹介です。

sokot

最近2週間ぐらいで sokot というコマンドラインツールを作りました。

github.com

会社では KING OF TIME で勤怠管理をしているのですが、そのAPIを叩いてチームごとの残業時間を集計するものです。

Regional Scrum Gathering Tokyo 2018 に参加してきました - しょ〜うぃん広場

の記事にも書きましたが、スクラムの手法においてスプリントのベロシティーが上がっているように見えていても、実はチームの開発効率はあがっておらず、単に労働時間が増えているだけだった。という可能性があります。 そのような事態が起きていないことを確認するために、このツールを作成しました。

sokot の名前は Scrum-Overtime-KOT(KING OF TIME) の頭文字から来ています。

インストール

Python3 が入っている環境で

$ pip install sokot

だけで完了です。

使い方

まずは初期設定です。

$ sokot configure
Token:  # APIトークンを入力
Saved to '/Users/showwin/.sokot/token'

Sprint Length (Default: 2):  # 何週間のスプリントで実施しているか入力
The First Scrum Day (Default: 2018.01.01):  # スクラムを始めた日を入力
Saved to '/Users/showwin/.sokot/config.json'
OK

設定ファイルはすべて ~/.sokot/* 配下に保存されます。

トークンが有効であることを確認しましょう。トークンを発行する時に指定したIPアドレス以外からリクエストを送ると False が返ってきます。
(私はIPアドレス制限があることをすっかり忘れていて、貰ったトークン使えないじゃん!ってサポートに問い合わせました…笑)

$ sokot available
True

次にチームの登録をします

$ sokot group add dev_team_1 0003 A0004 0011

このコマンドではメンバー3人の dev_team_1 チームを登録しています。 メンバーの番号はKOTの管理画面に出てくる、下の枠内の数字です。 f:id:showwin:20180226090426j:plain

これで準備完了です。

$ sokot overtime
+------------------------------------------+------------+
|                Sprint No.                | dev_team_1 |
+------------------------------------------+------------+
|   Sprint #1 (2018-02-05 - 2018-02-18)    |   45.97    |
+------------------------------------------+------------+
|   Sprint #2 (2018-02-19 - 2018-03-04)    |   26.35    |
+------------------------------------------+------------+
|   Sprint #3 (2018-03-05 - 2018-03-18)    |   34.73    |
+------------------------------------------+------------+
|   Sprint #4 (2018-03-19 - 2018-04-01)    |   28.01    |
+------------------------------------------+------------+

チーム dev_team_1 の3人が2週間の間に残業した時間が出力されます。

Future Work

今後の追加機能としては、残業時間合計をメンバー数で割って、一人当たりの平均残業時間を出力することと、HTTP Proxyの設定を追加できるようにすることを考えています。 APIが固定のIPからしか叩けないので、おそらくどこかIPを固定したサーバーからこのツールを叩くことになると思うのですが、毎回そのサーバーに入るのが面倒なので Proxy 機能欲しいなぁという感じです。

requestsのproxy を使えばサッとできると思ったのですが、squid で立てているプロキシサーバとなぜかうまく繋がらずハマッています…

Team of Teams を(途中まで)読んだ

2018年は3週間毎に技術の勉強と、組織/マネジメントの勉強を繰り返す予定を立てていますが、1月21日~2月10日は後者の勉強期間です。 (1月1日~20日はVue.jsを勉強してたのですが、思ったより時間がかかっていて終わってません…)

2017年末から TEAM OF TEAMS (チーム・オブ・チームズ) を読んでいたので、今回の勉強期間ではその続きから読むことにしました。 全体の55%ぐらいしか読んでいないですが、簡単にまとめます。(途中で諦めた理由は後述)

本の概要

本の主張としては「トップダウンでマネジメントしていく従来の方法では、変化が激しくより複雑である近年の課題を解決するのは難しい。下部のチーム/個人に十分な権限を与えて主体性を持って行動させることによって、それらの課題を解決することができる。」というものであったと思います。

この主張の正当性を主張するために、米軍とアルカイダの戦闘の例や、NASAアポロ計画についての事例が取り上げられています。(こういった事例の紹介が本のほとんどを占めていたため、残りの45%は読むのをやめてしまいました。。実は後半の方が大事だったりして…)

米軍とアルカイダの戦闘の例を紹介すると、 米軍は過去の成功体験から、ピラミッド型のトップダウンな組織で構成されており、各チームにはプロジェクトの目標とそれに関する必要最低限の情報のみが与えられている状況でした。 そのためあるプロジェクトの途中に他のチームにとってはとても貴重である情報を見つけたとしても、その価値が分からずに見逃してしまい、与えられた目標のみを追いかける内に向いた組織になってしまっていました。 一方でアルカイダは、末端の戦闘員までアルカイダの最終目標を認識しており、それを達成するために全員が同じ方向を向いて、目標達成のために何をすべきなのか自分で考えて行動するような組織構造ができあがっていました。 (個人的には「ピラミッド vs WWW(ワールドワイドウェブ)」な対象的な組織構造だと感じました。)

そのためアルカイダの幹部を暗殺しても、組織全体が方向を見失い壊れてしまうようなことはなく、アルカイダの撲滅には苦労したようです。 また毎回目標や戦略が上から降ってくる形になっていた米軍は、その間に戦況が変わっていてそれが全く役に立たないものになっている場合もあり、素早い状況の変化に対応できない構造になってしまっていました。

そこで、米軍は「チームの中のチーム」という方針で、配下のチーム同士の関係が単独のチームの内でのメンバー同士の関係に似た組織構造を作ることにしました。 つまり今までは上下関係の間でのみ情報共有がなされていましたが、方針の転換によりチーム同士の横関係の間でも情報共有が許されるようになりました。 情報共有についてだけではなく、役割、意思決定権限、リーダーシップに関しても、従来とは全く逆の手段が導入され、アルカイダと同じように末端のチームで意思決定が行われるようになったのです。


この本は、某なんとかStationというゲーム機を作っている会社のマネジャーさんにオススメされて読み始めた本なのですが、某社ぐらいの大きな組織だと、この本から学ぶことは多いのかもしれないと感じました。 私自身大きな組織に属したことがないので、ピラミッド型組織の課題感を肌で感じたことがないのですが、これから弊社が大きくなっていく中でどういう組織構造を作っていくべきなのか、少し明確になった気がします。

組織/マネジメント勉強期間はあと1.5週間あるので、昨日から 新1分間マネジャー という本を読んでいます。こちらは薄い本なので、1時間で60%ぐらい読んでしまったのですが、マネジメント素人にはこちらのほうが学びが多いです(笑) こちらも読み終わったらまとめ記事を書こうと思います。

Regional Scrum Gathering Tokyo 2018 に参加してきました

気分が良いので、1日で2記事書きます。笑

1月11,12日で Regional Scrum Gathering Tokyo 2018 に参加してきました。 イベント自体は13日まであるのですが、2日間で得た学びが多く、これ以上インプットすると頭が弾けそうだったので、2日でやめておきました。

参加したきっかけ

弊社 scouty では複数人開発が始まった2017年10月からスクラム(っぽい)開発を始めています。 開発メンバーはだれもしっかりとしたスクラムでの開発経験がなかったため、始めの一ヶ月半ぐらいスクラムの経験が豊富な外部の方にアドバイザーとして入ってもらっていました。

プロセスの改善を続けて、最近では落ち着いてスクラムな開発ができるようになってきたのですがまだまだ不安な点もあり、ちょうど関わりのあった eureka の @kajinari さんに相談したところ、このイベントを紹介してもらいました。

イベントで学んだこと

聞いていた発表はだいたいTwitterでリアルタイムまとめをしていました。 #RSGT2018 showwin で検索するとみれます。

twitter.com

自分的に良いなと思ったものをいくつか列挙すると、

これは1日目のKeynoteの内容なのですが、会場でも頷いている人が多かった話でした。 今回のイベントでも、これ帰ったら試してみよう!というものがいくつもあった(後述)ので、 うまくいくかわかりませんが自分のチームで試してみたいと思っています。

Run the experiment !!


(スレッド機能でつなげてかいていたので、前のツイートも表示されてしまっています)

サイボウズさんで、ウォーターフォールからスクラムに切り替えたことで得られたメリットの話です。 うちのチームではまだまだこれらのメリットを享受できていないので、こうなれるようになりたいなと強く思いました。

・残業がほとんどなくなった

(発表では触れられていませんでしたが)ベロシティが上がっているように見えているけど、実は残業時間が増えているだけだった、ということが起きうるなと自分で勝手に思っていました。

スプリントレビューの時にベロシティの確認と一緒にチーム全体の残業時間を確認してみると面白そうなので取り組んでみます。

・スプリントの計画を達成した後のんびり過ごす (空いた時間でKAIZEN)

に関しては、いろいろと思うことがあります。

私はスタートアップ(scouty)で働いているのですが、完全に同じことをしている競合は今のところいないため、先行優位性を活かして(なるべく早く製品を成熟させ)今のうちにマーケットを取りに行きたいという会社としての思いがあります。

そのため、今スプリントの計画を達成したら、次スプリントのバックログからタスクを引っ張ってきて新しい価値の提供に取り掛かりたいのです。 そしてまた、そうすることでのみチームのベロシティが向上していることが測れるのでは?とも思います。

一方で、その方法ではスプリントの計画を早く達成しても何のアメ(ご褒美)も与えられず、高いモチベーションを保って開発を続けるのは難しいとも感じます。 KAIZEN系のタスクを定義してスプリントに突っ込むのは、"やらされてる感"があってちょっと違うなぁとも思い。なかなか自分の中で納得いく答えが出ません。 (私も"やらされてる感"のある仕事って大嫌いなので、ちょっと空き時間に「ちょっとこのページの描画遅いと思ってたから高速化しといたよ🤤」みたいなことをしたいんですよね。。)

ここは組織の状態によって答えが違う部分な気がするので、POとちゃんと話し合う必要がありそうです。

・ペアやモブワークを行うことが多くなった

この発表に限らず、いろいろな人と話していても、うちでも取り組んでいるよ。という話をよく聞きました。 スクラムガイドには、開発チームの特徴として

• 機能横断的である。インクリメントを作成するスキルをチームとしてすべて備えている。
(略)
• 開発チームのメンバーに専門能力や専門分野があったとしても、最終的な責任は開発チーム全体が持つ。

とあり、開発チーム全員が共通なスキルセットを持ち、どのタスクでもこなせることが理想であると書かれています。 そのために、みなさんスキルトランスファーを目的として実施しているようでした。

その他にも複数人で開発することで、タスクを誤解していてレビューされてやり直しになる、のようなことも起きなくなり、レビュー済の状態に近い精度で開発ができるメリットもあるとのことでした。

弊社でも、ネット上の不定形/非構造なデータを扱っていることや、(機械学習まではいかないレベルの)複雑なドメインロジックの実装が多いこともあり、タスクによってはレビュー→差し戻しが多く発生するものがあるため、そういった難易度の高いタスクに関してはペアワークをすることで開発効率があがるかもしれないと思いました。


これについては私も同意で、技術が発達したことにより高い専門性を保つためには、多くの時間を学習につぎ込まないといけない世の中になっていると思います。

個人的には、バックログのうち8~9割ぐらいのタスクについては全員ができ、他プロダクトとの優位性に関わるような1~2割の部分は高い専門性をもった人しかできなくても仕方ないと思っています。 むしろその1~2割ができる稀有な人材を確保できているからこそ、その組織が他に勝てるのではないでしょうか。

弊社では採用基準の一つに「既存のメンバーが持っていない特長(スキル)をもっていること」というものがあります。当然人が増えていくにつれてこの条件を満たすのは難しくなっていくため、どこかでこの条件を諦めないといけなくなるフェーズは来ると思っていますが、なるべく長く続けていき最強のチームを作りたいと思っています。

今回答えがわからなかったところ

私自身 SCRUM BOOT CAMP THE BOOK を読んで、イベント中に スクラムガイド の存在を知ったぐらいの勉強不足スクラム初心者なので、CSMの研修などを受ければわかるようになるのかもしれませんが、デイリースクラムのフォーマットの価値が未だによくわかっていません。 スクラムガイドには

• 開発チームがスプリントゴールを達成するために、私が昨日やったことは何か?
• 開発チームがスプリントゴールを達成するために、私が今日やることは何か?
• 私や開発チームがスプリントゴールを達成するときの障害物を目撃したか?

を共有すると書かれています。「輪になって口頭で共有する」とは書かれていませんが、イベントに参加してこのようにやっているチームが多いように感じました。

弊社では、上記2つについてはデイリースクラム前にSlackで各自文字ベースで報告するようにしており(そもそもKANBANを見ればわかる)、デイリースクラムではBurndownが予定通りかと、障害物がないかの2点のみ確認するようにしています。それにより時間短縮ができ、Burnが予定どおりではなかった場合に、小さなふりかえり/スプリント計画をデイリーで行えています。

デイリースクラムの目的が "スプリントゴールを達成するため" であれば、単なる報告会よりもこちらの方が有効な気がしているのですが、どうなんでしょうか。 答えをお持ちのスクラムマスターな方々 @showwin にツッコミ頂けたら嬉しいです! (答えを頂いたので最下部に追記しています)

帰ったら試すもの

  • スプリントレビューでベロシティと一緒にチーム全体の残業時間を確認する
  • 複雑なタスクはペアワークで取り組み、生産性があがるのか、働き方に対する満足度が上がるのか確認する
  • スプリントレビューで機能開発タスクとバグ修正タスクの比率を確認する (長期的に見て70%機能開発が理想)
  • スクラムイベントのファシリテートを別の人にやってもらう (スクラムマスターがでしゃばりすぎず、開発チームにも主体的に動いてもらうために、一度経験してもらって何か変化があるのかみてみたい)
  • POもリファインメントに参加する。(現状開発チームがメインでリファインメントしているが、タスクの定義が曖昧なものもあるので、事前にPOに行ってもらう)
  • リリース可能かどうかはPOが判断する。(POが忙しいので、SMの私が品質の確認もしてしまっている状態)

代表がPOをしているのですが、経営に集中させたいので、(エンジニア社員が増えたら)そこからPOを任せる人を別で立てないと、今のままでは役割を十分に果たせないなと感じています。

おわりに

Regional Scrum Gathering Tokyo 2018 の運営に関わっていた皆さん、ありがとうございました!とても勉強になったカンファレンスでした。来年も参加します!

繰り返しになりますが、イベントを紹介してくれた @kajinari さんありがとうございました!!

追記

@ryuzee さんと @haradakiro さんからデイリースクラムについてご意見頂きました。ありがとうございます!

上で私が参照していたのは、2016年7月版のスクラムガイドでしたが、2017年11月にスクラムガイドの改訂があったようです。

2017年11月版では、デイリースクラムの章に以下のような説明がありました。

デイリースクラムは、開発チームがスプリントゴールを達成する可能性を最適化する。開発チームは、自己組織化チームとしてスプリントゴールを達成し、スプリント終了までに期待されるインクリメントを作成できるかを毎日把握しなければいけない。
デイリースクラムの構成は、開発チームが設定する。スプリントゴールを目指している限り、他のやり方で行なっても構わない。質問を使うチームもあれば、議論ベースで進めるチームもある。たとえば、以下のような例を使用するといいだろう。
• 開発チームがスプリントゴールを達成するために、私が昨日やったことは何か?
• 開発チームがスプリントゴールを達成するために、私が今日やることは何か?
• 私や開発チームがスプリントゴールを達成する上で、障害となる物を目撃したか?

中身の例として上の3つが提案されている形になっており、 "開発チームがスプリントゴールを達成する可能性を最適化する" 方向を向いていれば他の方法でも問題ないようでした。

2017年の振り返りと2018年の目標

ブログの最後の記事を見たら2016年8月でした。

大学の同期が立ち上げた scouty にJOINした2016年11月から一度もブログを書いていないことになりますね。 1年以上もブログ書いていないとは思っていなかったのでびっくりしました…

今年はちゃんと書こうと思っているので、2017年の振り返りと2018年の目標から書いていきます。

2017年の振り返り

10月までは自分がほぼ一人でプロダクトの開発をしていたので、そこに全力コミットする事が多く、今まで勉強してきたことをアウトプットし続ける年でした。 下半期は採用活動に注力したこともあり、幸いにも10月2人、12月に1人エンジニアが入社してくださり、今では4人体制で開発しています。

高い開発速度を保ちつつも、後から入ってくるエンジニアのために、ドキュメント化や保守しやすいコードを書いていたつもりでしたが、 いざ人が増えると、ドキュメント化されていない属人化された知見が大量に存在することが露呈し、コードも保守性が低くDDDで書き直す大規模なリファクタリングを行うことになってしまいました。

10月からの2ヶ月間で大規模なリファクタリングも無事に完了し、最近では(比較的複雑なビジネスロジックが多いのですが)開発に必要な裏側のロジックへの理解も開発チームに浸透してきた感じがします。 2018年はさらに人を増やしつつも、彼らを中心に更に高速な製品開発ができそうで楽しみです。

2018年の目標

2017年はほとんどインプットせず(学んだのはPython, Djangoぐらい)、アウトプットばかりしていたので、今年はインプットメインで行きたいなと考えています。 目標は2つ設定しました。

input を多めにする

・3週間に1冊、技術本と組織本を交互に読む
・仕事以外のコードも積極的に書く

エンジニア文化の形成

・高い生産性、知識の共有、自発的な学習、自立性
・(e.g.) スクラム、ペアプロ、社内LT

勉強したい内容に関して、技術面では以下の3つを重点的にやっていきます。

  • 2017年の課題としてあがった、保守性/可読性の高いコードを書くためにデザインパターンの勉強
  • 今後プロダクトでVue.jsを使うことになるので、フロントエンドの勉強 (今のスキルセットはインフラ-バックエンドメイン)
  • 機械学習/自然言語処理 周りの基礎的な学習 (社内でWeb開発チームと機械学習チームのパイプ役をするため)

マネジメントや組織づくりに関しては、スクラムや強い組織づくりについて重点的に学び、開発チームが120%の力を出してプロダクト開発に取り組める環境を作れるようになりたいと思っています。

もう一つの目標として、エンジニア文化の形成があります。 scoutyでは採用の基準の一つに、「既存の社員に持っていない特長をもっていること」を掲げており、コードの設計に強いエンジニアや、DBにめちゃくちゃ詳しいエンジニアがいます。彼らが持っている知識を他のエンジニアに伝搬させていくことで、組織全体のスキルが底上げされ強いチームを作ることができると信じています。 そのためにもペアワークや社内勉強会などいろいろと挑戦してみて、良い文化を作り上げていきたいと思っています。

私は学生時代も前職も受託開発をしていて、今まで0→1で製品の開発経験ばかりしていましたが、今年は 1->10 あるいは 10 -> 100 にしていくフェーズのため、エンジニアとしても新たな課題にぶつかるでしょうし、(そもそも全く経験したことのない)マネジメントの業務も発生するので、2018年は大きく2面から成長できそうで楽しみです。

任意のSQL文で mysqldump できるツールを作った

現状

$ mysqldump --query '任意のSQL文' > mydump.sql

のような事をしたかったのだけど、mysqldump では --where オプションで

$ mysqldump mydatabase users --where 'id IN (SELECT user_id FROM hoge WHERE huga > 10) AND id > 1000'

ぐらいのことしかできず、キーが1つの場合の JOIN を IN に書き直せるぐらいが限界になる。

別の方法としては mysqldump を使わずに

$ mysql -e "SELECT * FROM users" mydatabase --xml > mydump.xml
$ mysql --local-infile -e "LOAD XML LOCAL INFILE 'mydump.xml' INTO TABLE users;" mydatabase 

とすると任意のSQL文が使えるが、XML形式でしか出力できないため大量のレコードを出力する際にはダンプのファイスサイズがかなり大きくなってしまう。中身はこんな感じ。

$ cat mydump.xml
<?xml version="1.0"?>
<resultset statement="select * from users
" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <row>
    <field name="id">1</field>
    <field name="first_name">sato</field>
    <field name="last_name">huga</field>
    <field name="age">19</field>
    <field name="country">JP</field>
    <field name="created_at">2016-08-13 08:45:58</field>
  </row>

myquerydump 作った

そこで showwin/myquerydump をつくった。 これを使うと

$ myquerydump mydatabase "SELECT * FROM users" > mydump.sql
$ mysql mydatabase < mydump.sql

のように export/import できる。 ダンプファイルの中身も mysqldump と同じように SQL で書かれているのでファイルサイズも大きくならない。

$ cat mydump.sql
LOCK TABLES `users` WRITE;
INSERT INTO `users` VALUES ('1','sato','huga','19','JP','2016-08-13 08:45:58'),(…
UNLOCK TABLES;

ファイルサイズを比較してみると、このようなテーブルの300万レコードで以下のようになる。

mysql> desc users;
+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| id         | int(11)     | NO   | PRI | NULL    | auto_increment |
| first_name | varchar(64) | YES  |     | NULL    |                |
| last_name  | varchar(64) | YES  |     | NULL    |                |
| age        | int(11)     | YES  | MUL | NULL    |                |
| country    | varchar(64) | YES  |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+
mysql> SELECT COUNT(*) FROM users;
+----------+
| count(*) |
+----------+
|  3000000 |
+----------+

$ ls -lh
104M  users.mysqldump
104M  users.myquerydump
551M  users.xml

XMLで出力した場合と比べて20%弱ぐらいのサイズになり、当然だが mysqldump と同じぐらいになる。

便利オプションの紹介

例えば

$ myquerydump mydatabase "SELECT users.name, prefectures.name FROM users INNER JOIN prefectures ON users.prefecture_id = prefecture.id ORDER BY users.name" > my.dump
$ cat my.dump
LOCK TABLES `users` WRITE;
INSERT INTO `users` VALUES …
UNLOCK TABLES;

のように複数テーブルのカラムを SELECT してダンプを取る時には大抵 INSERT 先は users テーブルでなかったりするので、勝手に INSERT INTO 'users' とされてしまうと困る場合がある。 そういうときには -t オプションでテーブル名を指定すると

$ myquerydump -t user_prefecture mydatabase "SELECT …" > my.dump
$ cat my.dump
LOCK TABLES `user_prefecture` WRITE;
INSERT INTO `user_prefecture` VALUES …
UNLOCK TABLES;

となって便利。

INSERT 前にテーブルを空にしたい場合には -add-delete-table オプションを付けると DELETE FROM が追加される。

$ myquerydump -add-delete-table -t user_prefecture mydatabase "SELECT …" > my.dump
$ cat my.dump
LOCK TABLES `user_prefecture` WRITE;
DELETE FROM `user_prefecture`;
INSERT INTO `user_prefecture` VALUES …
UNLOCK TABLES;

残りの細かなオプションは README#Usage を見て頂けると良いと思う。 基本的には mysqldump と同じオプション名になるように気をつけている。

問題点

速度が遅い!! 上の300万件ある users テーブルでこれぐらいの速度差がある。

$ mysql -e "SELECT * FROM users" mydatabase --xml > users.xml
=> 14 sec

$ myquerydump mydatabase "SELECT * FROM users" > users.dump
=> 78 sec

ファイスサイズが5倍になる mysql -e --xml を使うか、ダンプに5倍の時間がかかる myquerydump を使うかという選択をしなければいけない感じでイマイチ…

もう少し高速化して2倍ぐらいの時間でダンプが取れるようにしたい。

Webサイトの負荷検証ツールを作ってみた

先週仕事で、負荷検証をしてみたいかも!みたいな話がすこし上がって、どんなツールがあるのか調べてみたら、最近は Gatling というのがちょっとアツいらしい。 昔から使われている(らしい) JMeter はあまりパフォーマンスが出ないとか書いてある記事を見かけたけど、ぼくは使ったことがないのでよくわからない。

Gatling はパフォーマンスを重視して Scala で書かれているんだけど、リクエストのシナリオを書くのに ScalaDSL を書かないといけない。こんな感じ

class MySimulation extends Simulation {

  val conf = http.baseUrl("http://example.com")

  val scn = scenario("Gatling")
      .exec(http("index").get("/"))
      .during(10 minutes) {
    exec(
      http("json").get("/json")
        .check(jsonPath("$.id")
        .saveAs("id"))
    )
  }

  setUp(scn.inject(atOnceUsers(5)))
        .protocols(conf)
}

複雑なリクエストを送りたい時には使い勝手が良いのかもしれないけれど、ScalaDSL とかよくわからないし、書きたくないので、もっと簡単に負荷検証ができるツールを作ってみた。

hakari

ツールの名前は hakari で、測りたいから hakari にした。 Easy to Install, Easy to Write Scenario. をウリにしていて、カップラーメンを待つ3分の間にインストールから実行までできてしまう。

インストール

$ brew tap showwin/hakari
$ brew install hakari

リクエストシナリオを書く

# scenario.yml
TopPage:
  method: "GET"
  url: "http://example.com/"
Login:
  method: "POST"
  url: "http://example.com/login"
  parameter:
    email: "user@example.com"
    password: "secret_password"

負荷検証実行!!!

$ hakari
2016/02/21 18:12:47  hakari Start!  Number of Workers: 2
2016/02/21 18:13:48  hakari Finish!
TopPage
    200: 125 req, 238.66 ms/req

Login
    200: 110 req, 255.11 ms/req
    500: 15 req, 192.18 ms/req

あっという間に負荷検証できて、ビックリする。
上の例では、2並列リクエストでテストを行っていて、1分間にトップページが125回リクエストされて、平均 238ms でレスポンスが返ってきたことがわかる。

デフォルトでは2並列リクエストで1分間の負荷検証を行うけど、もう少し細かな設定もできて、HTTP header をカスタマイズしたかったら

# myconfig.yml
Header:
  Accept-Encoding: "gzip, deflate, sdch"
  Accept-Language: "ja,en-US;q=0.8,en;q=0.6"
  Cache-Control: "max-age=0"
  User-Agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.39 Safari/537.36"

と設定ファイルを書いて

$ hakari -c myconfig.yml -s scenario2.yml -w 10 -m 2

とすると、10並列リクエストで2分間 myconfig.yml に設定した HTTP header で scenario2.yml のシナリオを実行できる。

まとめ

hakari は Gatling や JMeter と比べると、結果表示部分のレポート機能がまだまだ弱いので、そこをもう少し強化する必要がある。逆に、レポート機能はそんなに充実してなくて良いので、手軽にどのぐらいのリクエストをさばけるのか負荷検証したいという場合には hakari を使うと良いと思う。

昨日の午後から開発し始めて、24時間でこのぐらいのツールが作れてしまうので、Go 言語はすごい。 ぼくはすごい Gopher ではないので、テストコードも書いていないし、おそらく Go らしいコードも書けていない。。もっと勉強しなければ。

便利!! と思った方は、遠慮せずに GitHub Star ください!! → showwin/hakari