mizzsugar’s blog

日々感じていることや学んだことを書きます。エンジニアリング以外にも書くかもしれません。

【読書録】失敗から学ぶRDBの正しい歩き方

この本は著者の方の経験から得たプラクティスが書かれていて実用的かつわかりやすくてとても勉強になりました!

Amazon CAPTCHA

読んでみようとした経緯

  • 良書だと聞いて
  • MySQLPostgreSQLで意識すべきところを知りたい

読むモチベーション

  • チーム開発で説得力のある根拠をもって話し合いたい
  • 自分は経験してない失敗を学んで同じ失敗をしないようにしたい

概要

MySQLPostgreSQLの違いに関して扱っているのは20章あるうちの2-3章くらいでした。他はどのRDBMSにも共通するようなテーブル設計、クエリ、運用のアンチパターンでした。

ただし、共通するアンチパターンの章の知識があるとよりMySQL, PostgreSQLの違いと付き合い方が理解できるので、良い構成だと思いました。

また、運用まで見据えているのは嬉しかったです。

読み終わって、自分の経験を振り返って、アンチパターンを踏んでしまっている人はみんな良かれと思ってやっているなあと思いました。良かれと思っているからこそ「○○という本に書いてあるアンチパターンも知らずにやっているあいつは勉強不足」と責めず、アンチパターンが良いと思った理由を聞きつつ、こちらがデメリットに感じている根拠を感情に任せず伝えると建設的だと思いました。また、振り返ると、アンチパターンでうまくいった経験があるからアンチパターンを踏むべきと思っている人が多かった気がします。ただし、その経験でのシステムと今取り扱っているシステムは違うので、過去の栄光は一回置いといて今求められていることと目の前のデータの中身を良くみないとアンチパターン踏むのが許容されるかどうかはわからないので気をつけたいです。


この本で特に学びになったこと

1. カーディナリティとフラグの闇

フラグがあるとINDEXがあまり効かない場合があります。その鍵は「カーディナリティ」です。この言葉を初めて知ったのですが、「列に格納されるデータの値にどのくらい種類があるのか?」の指標だそうです。種類が多い、つまり重複が少ないデータはカーディナリティが高いと言えます。カーディナリティが高ければ高いほどINDEXをうまく利用しやすいです。

この本では、カーディナリティが低い例として性別フラグを示しています。genderという列には 1= 男性 2 = 女性 という値しかありません。where gender = 1 のように絞り込むと検索結果が多くなりやすくINDEXがうまく活用できていません。

他にも、「削除フラグ」や「ユーザーの入会手続き中・アクティブ・退会済ステータス」「送信ステータス」などよくやってしまいそうな例を上げていました。(私も一つやってしまったけどまだ直せそうなので直したいです。)

何でもかんでも状態をもたせてはいけないというわけではなく、以下のものなら状態をもたせることが許容されます。

  • 対象テーブルが小さくINDEXが不要
  • そのテーブルに頻繁にJOINすることがない
  • UNIQUE制約が不要で、外部キーでデータの整合性を担保する必要がない


2. ORMに依存しないには

私は今、HTTPからORMまですべて揃っているWebフレームワークを使って開発しているのですが、使いにくさの原因が具体的に言語化されました。

テーブル設計がライブラリに依存していること、テーブル設計がViewに依存しやすいこと、ビジネスロジックがテーブル設計に引きづられることです。

ORMは完全にRDBMSに抽象化したものではなく、N+1問題やINDEXの効かないSQLを発行する恐れがあるので常にSQLを意識する必要があります。

その結果、ORMのモデルを直接ビジネスロジックに使うと、ビジネスロジックの中で、業務の感心ごととは関係ない、N+1問題を解決するための方法などSQLの都合が書かれていて書きづらいのだなと分かりました。

これに対して、「Modelの中でデータを取り出す層」(ORMのモデルを扱う層)と「取り出したデータを加工する層」(データのCRUD部分だけ行うリポジトリ層)を分けることが提案されています。

リポジトリ層では、こういったORMが抽象化しきれなかった部分も包みこみます。

モデルを直接ビジネスロジックに使わず完全に抽象化したリポジトリ層を使うことでビジネスロジックの中にSQLの都合を書かずに済んで良さそうです。

PHP製のフレームワークSynfonyはこの考え方を予め用意しているそうです。


3. MySQLPostgreSQLのロックの違い

MySQLPostgreSQLでのロックの範囲の違いから生じたシステムの不具合が紹介されていました。

この本の中で特にMySQLPostgreSQLの違いが強調されていたのはロックについてのように思えます。

PostgreSQLではSELECT文でも一番小さいレベルのロックを取られるとは知りませんでした。

明示的なロックでないと、このような前提知識がないとロックに気づかないのでちゃんとRDBMSのドキュメントを読んでSQL叩くサンドボックス環境作って実際に動きを確かめて学ばないとと身が引き締まりました。