2025/01/02
2025/01/02
失敗から学ぶRDBの正しい歩き方を読んだのでまとめていく
過去の事実(値・過程)が失われると例外処理やトラブル時の状況把握で情報が不足してしまう。 作業ログやエンプラ系の実務ではよく発生する。データの履歴を保存することが大事。 ようは、事実が発生した後に、その事実を修正するための処理を行うことができるか、ステータスが変わっている時にその遷移を追うことができるかなどを考える必要がある。 ただし、履歴の保存はデータ量が増加したときのパフォーマンスとのトレードオフになる。履歴を持つ以外にも遅延レプリケーションを使ったり、Elasticsearchなどの分析ツールに保存するということもできる。
不要なJOINとJOINの回数が増えると計算量が増加する。 JOINの高速化のためのアルゴリズムとして大きく3つ挙げられている
JOINの回数を減らすためには、JOINの回避やJOINの条件を見直すことが大事。 特にJOINするテーブルは先にデータを小さくしてからJOINなどをすることを検討する。
INDEXとは、テーブルからデータを高速に取り出すためのRDBMSの仕組み。だいたいがB-Treeというデータ構造を使っている。 INDEXを効かせるためには、適切なカラムを選択することが大事。また、INDEXを貼るカラムのデータ型も重要。 ケースによってはINDEXを使ってくれないことも
カーディナリティとは、カラムのユニークな値の割合のこと。カーディナリティが高いほどINDEXを効かせやすい。 INDEXを利用するためには、次の2つの条件が必要
INDEXを貼りまくると、更新系のクエリが遅くなる。複雑な割合INDEXを設定しすぎると、オプティマイザが不適切な選択をする場合があるらしい。 これらはMENTORの原則に基づいて対応したらいいらしい。
また、INDEXを設計する際には3つの質問をすることが大事
削除という「状態」を持たせるのがアンチパターン。削除フラグを導入することで以下のような問題が発生しやすくなる
アンチパターンの回避策として、「事実のみを保存する」が挙げられている。例えば、削除済み用のテーブルを作成するなど。 会員の状態を表すステータスを持つ場合もよくある。これらはそれらの状態を表すデータ型として持つのが良くないらしい。 かといってどうすればいいのかの言及があまりなかったように見える。 絶対に持たせたらダメというふうには書かれていなかったので、適宜注意しながら利用していくのだろう。
RDBMSのクエリ実行には処理の評価順序があり、ORDER BYはSELECTの後に実行される。 ページネーション時にLIMITとOFFSETを使うと、OFFSETが大きくなると処理が遅くなる。これは、OFFSETが大きくなると、OFFSET分のデータを取得してからLIMIT分のデータを取得するため。 OFFSETを使わずにページネーションを行う方法として、WHERE句で条件を指定して取得する方法がある。 例えば、次のページとして渡すのを最後に表示されたidを使うことで絞り込みが早くなる。しかし、途中のページを表示していたときにデータが追加されたり削除されたりすると表示されずに飛ばされる行が発生してしまう。 これらの解決策として、
どちらにせよ、適材適所で設計していく必要があり、ページネーションは難しい
制約を強くすることでデータの整合性を保つことができるが、反面柔軟性を失ってしまう。 例えば、仕様変更をしたいときに、制約が強すぎると変更が難しくなる。データ型を変更する必要が出てきたときに、レコード数が膨大の時にロックが長時間かかってしまい、参照も更新もできなくなってしまう。
MySQLの外部キー制約は、外部キー制約の子テーブルを更新すると、親テーブルの共有ロックを自動的にとるらしく、デッドロックの温床になる。 対応として、排他ロックを取ることで回避できるがパフォーマンスのボトルネックとなる。 ビジネスロジックや状態を持たない範囲で適切に制約をつけることが大事 制約に段階をつけるとするならば、
いい塩梅が難しそう
バックアップは大きく3つに分けられる
バックアップの設計をするときは、どの手法を採用するにしても次の指針について考える必要がある
バックアップを正しく行うために、次のようなポイントは押さえておきたい
エラーログ出力の設計として如何含まれていると良さそう
RDBMSのメトリクスとして何を監視したら良さそうか?
MySQLのロックの特徴としてギャップロックとネクストキーロックがある。 MySQLのロックの粒度は通常行ロック。ギャップロックは、
よく聞くACID特性
トランザクション分離レベルの種類として次の4つがある。
また、それぞれに発生する現象がある
MySQLの場合、REPEATABLE READがデフォルトで、Phantom Readは基本的には発生しない。ただし、SELECT...FOR UPDATEでロックを取得している時には直近にコミットされたレコードを返す。
フレームワークを利用することで、開発の生産性を高めることができる反面、フレームワーク独自の制約を受け入れる必要があり、依存すればするほどRDBMSを縛り付けることとなる。 特に、テーブル設計がライブラリに依存してしまった場合にテーブル設計に悪影響を及ぼすことがある。 フレームワーク・ライブラリと上手に付き合うための方法として次のようなものが紹介されている
データベースの寿命はアプリケーションより長い。データベースにフレームワーク都合の問題を一度持たせると、その問題と長く付き合うことになってしまうため、トレードオフを常に意識して設計をしていく必要がある。