会員登録すると
学習することができます。
会員登録する(無料)
登録済みの方はこちら
ログイン

変えるときの落とし穴 ― 状態の追加・一意制約・重い変更・消す前の確認

目安学習時間 20分

課題

全問正解でレクチャー完了です。

【問題1】

応募の状態に新しい値を1つ足すとき、この講座が「最初にやること」としているものはどれですか。

[選択肢]

【問題2】

すでに会員の書き込みがある大きな表に索引を足すとき、この講座の説明に合うものはどれですか。

[選択肢]
会員登録すると
学習することができます。
会員登録する(無料)

学ぶ目的

状態の値を1つ増やすと、読む側が知らない

応募の状態に「書類選考中」「面接中」「内定」があるところへ、「辞退」を足すとします。データベースに値を足すのは簡単です。困るのはその値を読んでいる側です。

  • 状態ごとに件数を数える集計が、「辞退」をどこにも数えない
  • 状態で分岐する画面が、知らない値で何も表示しない
  • 通知や外部への連携が、想定外の値で落ちる

第1回の「読む処理が増える」が、ここで効いてきます。状態を足すときは、その状態を読んでいる場所を先に全部探すことから始めます。知らない値が来たときに「落ちる」のか「その他として扱う」のかも、最初に決めておきます。

値を数字で持つなら、間を空けて番号を振るのも1つの手です。naminori の会員の職種は 10・20・30… と10おきに番号を振り、「その他」は 900 にしてあります。あとから間に値を足しても、並び順と既存の番号が崩れません。

一意の制約は、重複が無いのを確かめてからかける

「同じ会員が同じ求人を2回お気に入りに入れられない」ように、一意(ユニーク)の制約を後からかけたいとします。重複がすでにあると、制約は作れません(手元で確認)。

ERROR:  could not create unique index "index_favorites_on_member_id_and_job_id"

naminori では2026年7月に、いくつもの表に一意の制約を足しました。そのとき、本番で重複が0件だと確かめたものだけを対象にしています。お気に入りには重複があったので、いちばん古い1件を残して重複を消してからかけました。電話番号は重複があったため、制約をかけるのをやめています。

重い変更は、利用者を待たせる

データベースの変更の中には、終わるまで他の書き込みを待たせるものがあります。たとえば普通に索引(検索を速くするための目次)を作ると、作り終わるまでその表への書き込みが待たされます(手元で確認:別の接続からの書き込みが、待ち時間の上限で打ち切られた)。

表が小さいうちは一瞬です。でも、データが貯まった本番では数分かかることもあり、その間、登録や応募が止まります。

PostgreSQL には、書き込みを止めずに索引を作る CONCURRENTLY という方法があります。500万行の表で約2.3秒かかる索引作りの最中にも、書き込みは通りました。Rails では次のように書きます。

class AddUniqueIndexToFavorites < ActiveRecord::Migration[8.1]
  disable_ddl_transaction!
  def change
    add_index :favorites, %i[member_id job_id],
              unique: true, algorithm: :concurrently
  end
end

ただし、この方法が途中で失敗すると、使えない索引が残ります(手元で確認)。失敗したら、その索引を消してからやり直します。

消す前に、使われていないことを確かめる

列や設定を消すのは、足すより危険です。消したあとで「まだ使っていた」と分かっても、戻せないことがあるからです。

  • コードの中で、どこからも読まれていないかを探す
  • 本番のデータで、最近も書き込まれていないかを見る
  • 消すときは、まずコードから読まなくする変更を出し、それが本番で動いてから、データの側を消す(古いコードが動いている間に列が消えると、読む処理が失敗する)

戻せない変更は、戻せないと書く

既存の行を埋め直すような変更は、元の値が残っていなければ戻せません。naminori では、そうした変更には「戻せない」とコードに明記し、戻す操作を実行するとエラーで止まるようにしています。戻せると思って実行して、戻らないほうがずっと困るからです。

このレクチャーで学ぶこと

  • 状態の値を足すときは、読む側を先に探す
  • 一意の制約は、重複が無いのを確かめてから
  • 重い変更と、書き込みを止めない作り方
  • 消す前の確認と、戻せない変更の明記

質問

まだ質問は投稿されていません。

質問投稿

ログイン後に質問の投稿ができます。