こう 聞かれます
- 「読み込みが
増えて DB が 重い とき、 どんな 手を どの 順で 打ちますか」 - 「リードレプリカを
足せば 解決しますか」 (裏から聞く形) - 「DB を
分割 (シャーディング) するのは、 どんな ときですか」
面接官が 見ている点
- いきなり
大きな 構成の 変更に 飛ばず、 測って 原因を 特定してから 手を打つか - 安くて
戻しやすい 手から 順に 並べられるか - リードレプリカの
遅れで、 書いた 直後の 読み込みが 古くなる ことを 知っているか - 分割の
重さ (作り直しの 量、 戻しにくさ) を 分かったうえで、 最後の 手に しているか
短い答え
- まず
測って、 どの 読み込みが 重いかを 特定し、 SQL と インデックスを 直します。 いちばん安く、 効く ことが 多い 手だからです。 - それでも
足りなければ、 接続の 数を 整え、 よく 読まれて 変わりにくい物を キャッシュに 置き、 次に 読み込み専用の 複製 (リードレプリカ) へ 読み込みを 分けます。 - 複製は
少し 遅れて 追いつくので、 書いた 直後に 自分の 書いた 物を 読む 画面は 元の DB から 読みます。 表を 分割するのは、 ここまでで 足りない ときの 最後の手です。
この
少し 詳しい答え
打つ手の順番
安くて
- 測る
どの SQL が、 どれだけの 回数と 時間で 重いかを 掴みます。 CPU が 高いのか、 ディスクの 読み込みが 多いのか、 接続が 足りないのかも見ます - SQL と
インデックスを直す 全部の 行を 読んでいる、 同じ SQL を 何十回も 流している (N+1)、といった 物を 直します。 台数を 増や さずに 済むことが 多い手です - 接続の
数を整える アプリの 台数が 増えると、 DB への 接続が 上限に 近づきます。 コネクションプールの 大きさを そろえ、 必要なら間に 接続を まとめる 仕組みを置きます - 手前で返す
よく 読まれて、 少し 古くても よい物は キャッシュに 置き、 DB まで 来ないようにします - 読み込みを
複製に分ける 書き込みは 元の DB (主)、 読み込みは 複製 (リードレプリカ) へ 送ります。 複製は 台数を 足して 読み込みの 力を 増やせます - DB を
大きく する、分割する 1 台を 大きくするのは 早くて 作りを 変えずに 済みますが、 上限が あります。 表を 複数の DB に 分ける 分割は、 最後の手です
複製の遅れ
多くの
その間に
- 書いた
直後の 画面や、 自分の 書いた 物を 読む所は、 元の DB から読む - 書いてから
しばらくの 間は、 その 人の 読み込みを 元の DB に寄せる - 残高や
在庫のように、 古い値で 判断すると 困る 読み込みは、 いつも 元の DB から読む
複製の
分割を 最後に回す理由
表を
トレードオフ
キャッシュも
話す例は
よく ある間違い
- 測らずに、
まずリードレプリカを足す重い SQL は そのまま 複製の 上でも 重く、 費用だけ増えます - すべての
読み込みを 複製に送る 書いた 直後の 画面で 古い 値が 出ます。 読み込みごとに、 古くて よいかを決めます - 早いうちから分割する
結合や トランザクションが 使いにくくなり、 戻すのも大変です
深掘りの問い
- 「書き込みが
重い ときは、 どうしますか」 複製は 書き込みを 減らさないので、 書き込みを まとめる、 キューで 後回しに する、 要らない 書き込みや インデックスを 減らす、 それでも 足りなければ 分割、と答えます - 「キャッシュと
リードレプリカは、 どう 使い 分けますか」 同じ 結果を 何度も 読むなら キャッシュ、 条件が ばらばらで 同じ 結果に なりにくい 読み込みならリードレプリカ、と答えます - 「複製が
止まったら、 どうしますか」 読み込みを 元の DB か ほかの 複製に 寄せ、 元の DB が 耐えられるかを 先に 見積もっておく、と答えます
