この本読んで関連で気になったことググってたら今週末の土日終わってしまった。
とくにデータベース界隈で積極的に活動されている曽根 壮大さん(そーだいさん)の『失敗から学ぶRDBの正しい歩き方 (Software Design plus)』。
RDBを扱う業務で直面しうる失敗ケースと、そのケースがなぜ問題なのか、その問題がなぜ発生してしまうのか、その問題に事前/事後にどう対応すればいいのか。が簡潔明瞭にまとまっている良書でした。
大きいサービスのDBのつらみを解消する必要がある人にとっても、スモールなサービスでこれからテーブルをガンガン作っていくぜ!という人にとっても参考になる内容。
会社の先輩エンジニアが読んでいるのを見て、おととい購入してさきほど読み終わりましたがとても良い買い物になりました( ・v・)b
読んで印象に残った点
とくに参考になった点をまとめておきます。
DBのパフォーマンス最適化のためのMENTOR
DBのパフォーマンス最適化のための手順として、「MENTOR」というものが紹介されていました。
DBのパフォーマンス最適化モデル「MENTOR」
- Measure...スロークエリログ、DBパフォーマンスをメンタリングする。
- Explain...実行計画を見てクエリが遅くなっている原因を調査する。
- Nominate...ボトルネックを特定する。
- Test...ボトルネック改善後の処理時間を計測し、全体のパフォーマンスを評価する。
- Optimize...DBパラメーターの最適化を定期的に行い、インデックスがキャッシュメモリに載るように最適化する。
- Rebuild...統計情報やインデックス情報を定期的に再構築する。
自分の業務でもスロークエリになっている画面の改修を進めることがありますが、そのときに明確な手順を意識できていなかったので参考にできるよいまとめだなと。
「MeasureとExplainをしっかりやるべきなのに、まだまだできていないなぁ...。」とか振り返ることができた。
INDEXが効かないパターン
この本を読むまでは、「INDEX貼っときゃ検索速くなるんでしょ!」みたいな危険思想を持っていました。(今となっては危険思想だと分かるけど、INDEXなんとなく理解だったから危険だとも思ってなかったのがコワい...。)
そもそもINDEXはどのような仕組みになっているのか、INDEXはどのようなときにどんなメリットがあるのか、INDEXを貼るべき時と貼るべきではない時はどんな違いがあるのか...。
などなど、INDEXに関してゼロから理解することができました。
INDEX貼っていても意味がないパターンとして以下のような場合があると。
Indexを貼っても意味がないパターン
- 全体のレコード件数に対して、検索で絞る件数が多いとインデックス検索の方がフルスキャンよりも効率が悪い。
- (ex.インデックスの効果で4ブロックの検索で値を見つけることができるが、5個の値を検索結果として絞る場合は、4*5=20回の処理が必要。フルスキャンなら10×1で10回の処理で済む。)
- 全体の中での検索結果の数が20%以下の場合はインデックスでの検索の方が高速になる。
- WHEREまたはON条件にそのカラムを使っていない場合は、INDEX効かない。
- 検索条件に指定されないのはもちろん、検索条件に指定したカラムの値をそのまま使うのではなく、関数や計算結果として指定しているとインデックスが効かない。
- カーディナリティの低いカラムに対する検索ではINDEX効かない。
- カーディナリティ...列に格納されるデータの種類。(ex.性別は生物学的には男性・女性の2種類しかなくてカーディナリティが低い。)
- カーディナリティが低いということは、検索対象のデータが多くなることを意味する。先述した20%以下にならないのであれば、インデックス検索は行われない。
- あいまい検索の前方一致検索以外ではインデックスが効かない。全文検索インデックスはMySQLではMrongaなどがあるから、それらのツールを活用することもできる。
- 統計情報と実際のテーブルに乖離がある場合。
INDEXに対しての理解はまだまだ浅いけど、役割と仕組みがイメージできたのは良かった。
高負荷・スロークエリとなりやすいSQLのパターン
高負荷・スロークエリとなるSQLのパターンが以下。
高負荷・スロークエリとなるSQLのパターン
- JOINしすぎると、参照元のデータサイズが膨大になるので、WHEREなどで絞ろうにも処理が遅くなりやすい。
- WHERE指定するカラムにINDEXが貼られていないなど、検索の最適化をすることができていない。
- JOINするまえに不要なレコードを除いてJOINすることができていなくて、不要なレコードもJOINしてしまっている。
- VIEWテーブルを活用するなど、クエリの最適化以外の方法を検討できていない。
- VIEWテーブルを活用するなど、クエリの最適化以外の方法を検討できていない。
- SQLのステートメントの実行順序を理解しないと、最適なクエリをかけない。SQLのクエリでは、より前の段階で検索対象を少なくし、より後の段階では処理件数が少なくなっていることが重要。
SQLのステートメントの実行順序は以下。
FROM -> ON -> JOIN -> WHERE -> GROUP BY -> WITH CUBE/WITH ROLLUP -> HAVING -> SELECT -> DISTINCT -> ORDER BY -> TOP(LIMIT)
SELECT (Transact-SQL) | Microsoft Docs
この実行順序があたまに入っているのと入っていないのとでは、最適なSQLがかけるかどうかに大きな差が出そう。
最初のJOINの条件のところでJOINするテーブルの総数とレコード数をできるだけ絞っておきたいし、SELECTでASで別名定義したものをWHEREで指定しようとしてもできないのも納得だなと。
「SQLの実行順序」なんて、エンジニアとして基本中の基本なのかもしれませんが、ちゃんと理解できてなかったので改めて学べて良かった...。
全体を通して、ほかにもACID特性の話や、トランザクション分離レベル、削除フラグの是非や、外部キー制約の扱い、ロックの管理方法についてなど、エンジニアとして働く上で必ず業務で必要になる知見が満載でした。
これらの知見が実際に業務でよくある失敗例と、その失敗によってどんなつらみが生まれるか、そのつらみをどう解決すればいいのかという観点で簡潔にまとまっていて、RDBに関しての知識が十分になくてもスッと頭に入って来やすかったです( ・v・)b
そして何より、絶対的なこたえや解法はなくて、そのときのサービスの状況、業務仕様、データ量の変化などによって、最適解は変わってくるし常に変動するものなんだなと知ることができて、RDBもっと学びたい!と思わせてくれる本でした。
まとめ
以上、『失敗から学ぶRDBの正しい歩き方 (Software Design plus)』の書評でした!
RDBは普段業務でテーブル追加やデータ検証などで当然のように使う技術だけど、今まではなんとなくでも扱えてしまうからなんとなく扱っていました(扱える ≒ 直近で問題が顕在化することはない ≠ 適切に扱える)。
これまで、社内のデータベースエンジニアの会話で出てくる発言の一つ一つの隠れた真意・思考過程みたいなものが全くわからなくていちいち発言内容をググる...。でもなんでその方針がいいと判断されたのか分からない...。
そんな状況だったからこそ、読めてよかった良書だった( ´ v ` )
最後に、そーだいさんの資料でのメッセージをのせときます。
「技術で問題を解決する → 解決までの歩んだ轍が道になる」
「技術で解決した問題の価値がエンジニアの価値」
「自分自身で問題を解決していきましょう」
関連で読みたい資料・本
では!