読者です 読者をやめる 読者になる 読者になる

そーだいなるらくがき帳

そーだいが自由気侭に更新します。

今こそ知りたい、2大OSSデータベースのMySQLとPostgreSQLの違いについて話をしてきた

f:id:Soudai:20170525231808p:plain

去年書いたSoftwareDesignを題材にお話してください!って言われたので話してきました。
下の特集記事は1年経った今も現役で読める内容なので興味がある人はぜひ読んでみてください。
またRDBアンチパターンという連載をしていますのでこちらもあわせてご確認くださいっ!

gihyo.jp

そして当日の資料はこちらです。

SoftwareDesignにしっかりとMySQLPostgreSQLの違いについては触れているのでそこでは触れていない、ハマりどころや初めて両方のDBを知ったと言う人向けのカジュアルは部分を攻めました。
またDBだけの勉強会ですので普段説明するようなところは省略し、できるだけ経験談やコアの話に注力したつもりです。
このへんは資料に含まれて居ないので当日居た人たちだけの特典ですね!!

ということで実は今月は登壇3週連続だったのですが一段落しました。
来週はAWS Summitにブース出展するので今月は最後までバタバタするのですがこれを乗り切れたのは一つ成長したかなと思っています。
ここ数週間はアウトプットをかなり意識した日々だったので来月はしっかりインプットしたいです。
という事でMySQLPostgreSQLに興味が湧いたらぜひSlackのチャンネルに遊びに来てください。
みんなが暖かく迎えてくれますよ!!!

というわけでみなさまのご参加お待ちしています。

Javaエンジニアに知ってほしいRDBアンチパターン その3 について話して来た #jjug_ccc

Javaの国内最大カンファレンス、JJUG CCC 2017 springで登壇してきました。
僕の中で先週のオープンセミナー岡山の熱がまだ収まらぬ中の登壇だったのですが、多くの方に聴いていただけて嬉しかったです!
その時の資料がこちら。

RDBアンチパターンについてはPHPカンファレンスYAPC:Kansaiでも話をしましたが、今回は別バージョンです。

soudai1025.blogspot.jp

soudai.hatenablog.com

あのときはWeb系の人向けに話をしましたが、今回はエンタープライズな業務系の人向けです。
業務系は僕の印象では制約だったり、RDBの機能を有効活用してる印象があるのですが、逆に過剰になっていることが多い印象があります。
また論理IDなどデータ量が少なかったり、アプリの改修が少ないから死ななかっただけの設計も多く見られる印象です。
そういう点を今回お伝えしました。
また最後の「監視されないデータベース」については、多くのシステムに言えると思っています。
これはMackerelのポジショントークでしょ?って思われるかもしれませんが例えばpg_monzやPercona Monitoring Plugins for Zabbixでも良いと思います。
まずモニタリング監視しましょう。
PostgreSQLで言えばpg_statsinfoやpg_stats_reporterもあります。
インフラを可視化するというのはテストコードと同じです。

mackerel.io

リファクタリングはダイエットと似ています。
テストコードもモニタリング監視も体重計と同じです。
体重計に乗っただけでは体重は減りません。
テストコードもモニタリング監視もそれだけではアンチパターンから救ってくれるわけではありません。
ですが確実に一歩づつ改善していけば、より良い世界に進んでいけますし、その進捗が見えてきます。
だからこそ、今の現状に不満がある(アンチパターンがある)のであれば、これを機に前に進んで貰えれば嬉しいです。
品質の向上のために必要な初めの一歩ですのでこれを気に考えていただければと思います。

データベースリファクタリングについて話をしてきた #OSO2017

f:id:Soudai:20170516135259j:plain

岡山にはオープンセミナー岡山と言う最高のイベントがあります。

okayama.open-seminar.org

昨日は id:t-wada さんや id:naoya さんの資料がホットエントリー入りしてました。
この登壇はそれと同じイベントになります。
その他の方も超豪華講師陣の中で、私が出来る精一杯の経験も踏まえたお話をさせていただきました。

speakerdeck.com

この中で出て来る、データベースリファクタリングは本当に素晴らしい本です。
OracleベースなのですがMySQLだろうがPostgreSQLだろうが必ずためになる本です。
ですが、この本は既に廃刊になっており再販の予定もありません…
僕は後世に絶対必要な本の一つだと思っているので再販のためにも皆さんの要望の声を上げていただけるとうれしいです。
そしたらもしかしたら本が世に復活するかもしれません。

またSQLアンチパターンもご紹介しましたがこちらは絶賛販売中なので是非読んでください!!
最高です。

まだ読んだこと無い人は是非読んで下さい。

伝えたいこと

オープンセミナー岡山は最高のイベントなのは周知の事実なのでその件についてはまた別途まとめようと思います。
このエントリーでは資料には書いてないけど大切な事を伝えておきます。

結論、データベースリファクタリングは停止を伴うことも多々ありますし、複数のアプリケーションから1つのDBを参照していることも多々あるので政治的にも技術的にも影響範囲が広いです。
そこを乗り越えるためには入念な準備と適切な判断が必要です。
だから事前準備として

  • テストとモニタリングで変更前と変更後を正しく比較できること
  • 改善に対するチームの課題を共有すること
  • そのリファクタリングは本当に必要か本質を捉える事

なんかが大切になります。

本質について言えば「この設計は非正規されてる!直すんだっ!!!」と思ってもよく調べれば、JOINのコストを下げるための苦肉の策だったかもしれません。
またはMySQLで外部キー制約によるデッドロック回避だったかもしれません。
どちらも苦肉の策なのは間違いありませんが「兎にも角にも直すんだ!」とすると本質を見失います。
もちろん影響範囲が高いため、改修コストがメリット無いと判断されることもあると思います。
しかし糞なDBの上にどんなアプリケーションを組んでもクソという言葉もあるとおり、DBの設計はアプリケーション、サービス共に大きく影響を与えるのも事実です。
だからこそ、DBの変更には時間もコストも掛かるからこそ、定期的に小さく改善し続けることが長くデータを活かすコツだと思っています。
みなさんもこのエントリーを見て思うところがあれば、これを機に今日からデータベースリファクタリングを初めてみてください!

問題を小さいうちに解決させるってチームにとってとても大切ですよね

妻が実家に帰省中で、長男の面倒見ながら家事をしてそう思ったのでメモ。
例えば洗濯や食器の洗い物は貯めない方が手を付けやすいし、すぐ終わります。
すぐ終わるというレスポンスは次のハードルをまた下げてくれるので好循環を生みやすいです。
掃除やゴミ捨てだってそうです。
特に家事はマルチタスク処理を求められるので問題が大きなり、時間がかかると着手しにくくなります。
またすぐ子供から割り込みが来るので小さい問題を常に解決した方が全体として効率が上がります。
だからもし大きなタスクの場合は問題を細分化する必要がありますし、そもそも問題を小さいうちに解決していくことが大事だなと感じたわけです。
小さな問題の解決を世の中では割れ窓理論って言ったりハインリッヒの法則って言ったりするのでみんなも概ね賛同してくれると思います。
うちのチームでもプロダクト開発時に生まれた小さな問題を割れ窓と言ったり、リリース後の小さな問題解決を落穂拾いと言ったりします。

でもこれって家事以外でも言えるよね

ちょっと前に人が成長するためには問題解決する経験が必要で、そのためには適切なサイズの問題を用意する必要があるってことを考えたことがあります。

soudai1025.blogspot.jp

これとは逆に小さいうちに解決したほうが良い問題もあります。
例えばチームマネージメントと言うか、チームの不満とかは小さいうちに解決したほうがいいでしょう。
大きくなると歪みを生み、場合によっては派閥が生まれたり意図しない弊害が生まれて取り返しのつかない状態になります。
チームは当たり前ですが人と人の座組の結果ですから、勿論相性がありますし、相性が合わない事も多々あります。
チームが大きくなったり、長く所属してたり、座組に変化があったりなどのトリガーで大小の不満が生まれることはあります。
そんな感じでチームというのは生き物なので環境に合わせて常に変化しています。
ですのでチームの問題としていち早く察知し、素早く手を打てるか?と言うのはとても大切なマネージャーの仕事の一つです。
とは言え、チームの規模が大きくなれば全体を見るとどうしても細部が見えづらくなります。
そこで1on1をやったり、飲み会やったり、ランチミーティングしたりしてなんとかして小さな不満を探そうとするわけです。

本当に問題(不満)を見つけれてるのか

さて小さいうちに問題を解決したほうが良いこともそれがチームのために必要なこともわかりました。
どの経営者やマネージャーに聞いてもそれは理解を得られると思いますし、そのための努力をしていると言うでしょう。
しかし本当にチームの問題を汲み取れているでしょうか。
僕はマネージャーとプレイヤーを両方経験して思うのは、マネージャーが思っている以上にプレイヤーは不満を口にしません。
正確には「マネージャーの見える範囲」に出しません。
マネージャーの多くは直属のプレイヤーの評価者ですし、多くの裁量を持ちます。
ですのでプレイヤー自身のマイナスになる場合は不満を口にしないのです。
そして多くのシーンで「不満を口にする」のは意見具申ではなく、ただの愚痴として評価され、マイナスになると考えているのではないでしょうか。
特に不満先がマネージャー自身や組織自身にある場合は尚の事、組織批判やマネージャー批判と取られるので表に出づらいと思います。
その結果、不満が露呈するのは退職という形でであったり(そこでも多くの場合は本当の不満を口にせずに去っていくでしょう)チームの破綻によって気付かされるというのが最悪のケースです。

不満を言える雰囲気を作るには

結論、経営者やマネージャーが「メンバーと真摯に向き合う」としか僕はまだ答えを持ってません。
会社の金で飲み会や社員旅行をしても、モヤモヤボードを導入しても、マネージャー側に問題を解決する意志が無ければ形骸化するでしょう。
実際に現場では小さな問題の糸口はマネージャーの居ない喫煙所やランチ、会社からの帰り道で見つかる気がします。
これはやはり不満を言う事にメリットが無く、しかし不満をうちに溜め込むことが難しいからでしょう。
同僚に不満を口にするのは次の点があるかもしれません。

  • 同僚は評価者では無いため、デメリットが無い
  • 同僚がもしかしたら解決するためのアイディアを持っているかもしれない
  • 多くの同僚の同意を得られると噂話のような形でマネージャーに問題が伝わるかもしれない

これらはマネージャーの気持ちからすると「そんな遠回しな手順を踏まなくても直接言ってほしい」と思うかもしれません。
しかしあなたに直接伝えるメリットをプレイヤーが感じていないからこのようになるのです。
働くという字は人が動くと書いて働くですが、人は「自分のために動く」のですから当然そこにデメリットしかない場合はこのような結果になります。

また人手不足を声高に言う会社は多いですが、本当に今いるメンバーと向き合えているでしょうか?
新しい人を3人雇って2名辞めるチームは人の入れ替えのコストが高く、健全とは言えませんし、ブルックスの法則から見ても生産性が高いとはいえないでしょう。
心当たりのある経営者やマネージャーはそこから見直しをしてみては如何でしょうか?

じゃあSoudaiさんはどうしてるの?

会社では私は今はプレイヤーの立場で仕事をしており、マネージャーではありません。
ですがマネージャーの小さな問題を知りたいと言う気持ちを知っていますし、プレイヤーがマネージャーに伝え難い気持ちもわかります。
ですのでそこを上手く橋渡ししたり、情報収集して上手くマネージャーに提案することを意識してます。
また雑談を大事にしてます。
先程の喫煙所やランチタイムの例のように雑談には色んな本心が隠れています。
ですが雑談がなければそもそも情報収集する場もありません。
ですので雑談が少ないと感じれば雑談する場を作れば良いと思いますし、話を聞きたい人があれば食事に誘うなどの色んな方法があります。
リモートワークの場合はこの雑談がより難しくなるので工夫が必要だと思いますし、だからこそ色んなチームがビデオチャットを導入したり、社内Slackに趣味チャンネルや自分用のチャンネルを作ることを許容するのでしょう。

そして最近、もう一回プレイヤーに戻ってきて感じるのですがこれがデマルコの言う触媒のポジションなのかもしれません。

※デマルコと言えばピープルウェアですがデッドラインは本当に読みやすいのでオススメです

触媒というポジションは私の適正あるポジションの一つかもなと最近感じています。

まとめ

ということで問題を小さなうちに解決することは大切だと思います。
しかし実現するためには

  • 経営者やマネージャーが問題解決をするぞという意志
  • 小さい問題を集める仕組みやポジション
  • プレイヤー側の伝える工夫

などが必要で一筋縄ではいかないということがわかりました。
ですのでそれぞれのポジションが意識する必要があります。
またこれは普段の生活から意識すること多くの問題を解決すると思います。
まずは私もそーだい家と言うチームの長ですので家族と言うチームメイトの問題を解決するぞと言う強い意志を持って家族と成長したいと思います。

SourceTreeを実際に使ってエンジニア以外の人にGitを使って貰った話

タイトルのことを第21回 Tokyo Atlassian ユーザーグループで話してきました。

augj.connpass.com

登壇資料はこちらです。

speakerdeck.com

ざっくり言うとエンジニア以外の人にGitを使ってもらうにはGUI大事って話と僕たちは問題を解決したいわけで、なのでツールはそのための手段なので手段が目的になるのは駄目とは言わないけど本質は見失わないようにしましょうって感じです。

もうちょっと具体的に話すと、Gitというとコードを管理するモノってイメージ強いと思いますけど、実は色々と便利になります。
例えば定例MTGの議事録だって良いと思うし、手順書だってテキストで管理していいと思います。
そこにGithubやBitbucketを組み合わせると履歴が可視化されるし、プルリクエストを使うとより差分が明確になります。
こういうエンジニア向けの技術を柔らかくして、エンジニア以外の人にも使ってもらうことで全体の効率を上げることができるので、みなさまも是非チャレンジしてみてください!!

ということで今回AUGで久々にDB以外の話をしましたがこういうのも楽しいですね!
機会があれば他のイベントにもガンガン登壇したいと思いますのでお気軽にお声掛けください。

ほんとAtlassian、ユーザライクでコミュニティの楽しみ方知ってて大好きな会社です。

SoftwareDesignの連載をはじめました。

タイトルそのままにSoftwareDesignの連載をはじめました。

gihyo.jp

RDBアンチパターンと題してRDBの設計についてお話していきます。
なかなか胸に刺さる話となってますので今後の内容にもご期待ください!!

寂しかったのでブログ書きました。
現場からは以上です。

PostgreSQLで排他制約がめっちゃ便利!!

中国地方DB勉強会っていう控えめに言っても最高の勉強会があるんだけどそこで排他制約について教えてもらいました。

ikkitang1211.hatenablog.jp

排他制約って雑に説明すると重なりを拒否する制約です。 僕は使った事なかったのですが勉強会の中で事例紹介を受けて、めっちゃ便利だったのでここでご紹介します。

どんなときに使うの?

実際にはどんなときに重なりを制御したいかというとよく使うのは次の2つ。

  • 図面の重なり
  • 時間の重なり

1つ目は幾何学的な図面を表現するときです。 実際にPostgreSQLは円や四角をSQLで表現できます。例えば地図上で特定の座標から半径100メートルの円を書き、その中に特定の円(場所)があればErrorにするような制約が書けます。 そもそもSQLで位置計算もめっちゃ便利なので是非使ってみてください。

soudai1025.blogspot.jp

そして2つ目が時間の範囲での重なりの表現です。 PostgreSQLには範囲型というのがあります。 これは時間や数値の範囲を1つのカラムで表現できます。 例えば有効期限を表現する時、一般的にはstart_atとend_atのそれぞれのカラムを作成するのではないでしょうか。 この場合、 今日が有効期限に含まれるかどうか の点と線の比較は簡単ですが 特定の期間が有効期限に含まれるかどうか という検索は非常に面倒です。 しかし範囲型を使うと 5 <@ int4range(1,7) のように <@ で範囲と範囲の含有が簡単に検索できます。このように色んな演算子を用意しているので簡単に表現できます。

soudai1025.blogspot.jp

9.19. 範囲関数と演算子

実際の使い方

さて、ここまで読んで範囲型めっちゃ便利!!と思っていただけたと思います。 そこで例えば会議室の予約システムを作る時に範囲型を使うと次のように表現できます。

CREATE TABLE schedule
(
    schedule_id SERIAL PRIMARY KEY NOT NULL,
    room_name TEXT NOT NULL,
    reservation_time tsrange NOT NULL
);

demo=# SELECT * FROM schedule;

 schedule_id |  room_name  |               reservation_time
-------------+-------------+-----------------------------------------------
           1 | soudai_room | ["2017-04-16 11:30:00","2017-04-16 12:00:00")
           4 | soudai_room | ["2017-04-16 12:00:00","2017-04-16 12:30:00")
           5 | soudai_room | ("2017-04-16 12:30:00","2017-04-16 12:40:00")
           8 | soudai_room | ["2017-04-16 14:30:00","2017-04-16 16:00:00")
(4 行)

demo=# SELECT * FROM schedule 
          WHERE reservation_time @> '2017-04-16 15:30:00'::timestamp;

 schedule_id |  room_name  |               reservation_time
-------------+-------------+-----------------------------------------------
           8 | soudai_room | ["2017-04-16 14:30:00","2017-04-16 16:00:00")
(1 行)

demo=# SELECT * FROM schedule
         WHERE
    reservation_time && '[2017-04-16 11:45:00, 2017-04-16 12:10:00]'::tsrange;

 schedule_id |  room_name  |               reservation_time
-------------+-------------+-----------------------------------------------
           1 | soudai_room | ["2017-04-16 11:30:00","2017-04-16 12:00:00")
           4 | soudai_room | ["2017-04-16 12:00:00","2017-04-16 12:30:00")
(2 行)

しかしここで大きな課題として会議室は1つしかないので会議室の予約時間(reservation_time)が被ったらErrorになって欲しいですよね。 そこでお待たせしました排他制約の出番です。

EATE TABLE schedule
(
    schedule_id SERIAL PRIMARY KEY NOT NULL,
    room_name TEXT NOT NULL,
    reservation_time tsrange NOT NULL,
    EXCLUDE USING GIST (reservation_time WITH &&) ←排他制約を追加
);

demo=# SELECT * FROM schedule;
 schedule_id |  room_name  |               reservation_time
-------------+-------------+-----------------------------------------------
           1 | soudai_room | ["2017-04-16 11:30:00","2017-04-16 12:00:00")
           4 | soudai_room | ["2017-04-16 12:00:00","2017-04-16 12:30:00")
           5 | soudai_room | ("2017-04-16 12:30:00","2017-04-16 12:40:00")
           8 | soudai_room | ["2017-04-16 14:30:00","2017-04-16 16:00:00")
(4 行)

demo=# INSERT INTO schedule
  (room_name, reservation_time)
     VALUES
  ('soudai_room', '[2017-04-16 15:30, 2017-04-16 17:00)');
ERROR:  conflicting key value violates exclusion constraint "schedule_reservation_time_excl"
DETAIL:  Key (reservation_time)=(["2017-04-16 15:30:00","2017-04-16 17:00:00")) conflicts with existing key (reservation_time)=(["2017-04-16 14:30:00","2017-04-16 16:00:00")).

demo=# INSERT INTO schedule
 (room_name, reservation_time)
  VALUES
   ('soudai_room', '[2017-04-16 17:30, 2017-04-16 18:00)');
INSERT 0 1

ちゃんと弾いてくれてますね! これでUPDATEの設計にしてロックがアプリケーションパフォーマンスのボトルネックになったり、INSERTで表現する際のファントムーリード起因のbugとかを防ぐ事が出来ます。

まとめ

RDBに入っているデータは常に正しいといえる状態は精神衛生上もアプリケーションのロジック的にも平和なので排他制約使えるシーンは色々とあるな!と考えています。 とは言え僕も今回知ったばかりでまだまだ実務で使っていないので面白い使い方を模索したいと思います。

—- 2017/04/16 追記 —–

PostgreSQLで排他制約がめっちゃ便利!! - そーだいなるらくがき帳

CREATE EXTENSION btree_gist; して、EXCLUDEに (room_name WITH =, reservation_time ...) ってすると、同一room_name内で時刻が重複してたらはじくとかもできますよ!(room_nameが違えば通る)

2017/04/16 20:31
b.hatena.ne.jp

めっちゃ便利!!!!!

—- 2017/04/16 追記 2 —–

PostgreSQLで排他制約がめっちゃ便利!! - そーだいなるらくがき帳

単純な幾何学情報はともかく、地理的位置情報はPostGISも入れて扱うべきだというのはあまり知られていないのだろうか。

2017/04/16 22:05
b.hatena.ne.jp

みんなPostGISめっちゃ便利なのに知らない可能性あるのかって思ったので合わせて紹介します。

PostGISを使ってみよう | Let's Postgres

農研機構最高だぜ!(久々の定期ポスト

雑に説明するとPostGISは良い感じに幾何学的なことを出来るようにするPostgreSQLの拡張ライブラリの一つです。 例えば地球は球では無く楕円なので緯度経度から距離を計算する時に近似値計算ではズレが生じます。 なのでそこを正確に計算するためにはアレをコレしてと大変なのですがそこを良きに計らってくれたりします。 つまり正確な地図を表現したり、例えば町田は東京都に含まれるのか?みたいな複雑な形の確認も表現出来るようになります。 というわけで正確な地図を表現したい時にPostgreSQLPostGISは最強なのでオススメです。 あと皆さんも知ってると思いますがMySQL 5.7からInnoDBでもGIS型をサポートしてます。 こちらは機能的にはまだまだPostGISほどでは無いものの、光る部分も沢山あるので将来楽しみな機能です。 ということで地図などで座標を扱う時にPostgreSQLめっちゃ便利ですのでこちらも合わせて覚えてください!!