複合主キーをやめてユニークインデックス制約に移行する

2020/02/20 18:17:332020/02/20 19:03:41

導入
既存の複合主キーテーブルに対して A_I の id カラムを追加する で A_I カラムを追加して、無事ダンプが早くなってポータビリティが上がったんですが、実際に稼働させてみるとやばい問題が発覚
  • クエリ速度が地獄になった
  • IO がいっぱいいっぱい
  • こんなはずでは…
で、いろいろ調べたところこういう場合 複合主キー ではなく A_I の id カラムのみを PRI にして他の部分にユニークインデックス制約を貼るのが常套手段らしい
  • 事前に SELECT, EXPLAIN して速度テストしておけよ…という話ではある
  • 甘かった
いやなんやねんそんなことも知らんかったんかという感じではあるんですが、一応書き残してはおきます
  • 前の記事に追記したら記事の主題が失われてごちゃごちゃになってしまったので、別の記事として

ユニークインデックス
TypeORM では
uniqueindex.ts
@Index(["yuni", "kude", "attehosii", "kumiawase"], { unique: true }) 
export class Entity {...}
というふうに貼ると yuni kude attehosii kumiawase が同一のレコードが1つしか挿入できなくなります
  • 複合主キーでの挙動と同じですね
  • インデックスという名前ですが、この組み合わせでのインデックスの場合特段 yuni レコードの WHERE が早くなる挙動をしなかった
  • 組み合わせに特化したインデックスが作成されてそう
  • 各レコードにも @Column({ type: "int", unsigned: true, unique: true }) してたやつあったんですけど SELECT の速度測る前に今回やりたいこととは違うことに気づいてデータ飛ばしちゃったな
  • こうやると各カラムと同一値が挿入できなくなってしまう
  • A_I id の挙動としては理想
  • PRI で実現できてる

実際に実行するマイグレーション
migration.sql
ALTER TABLE `target_table` DROP PRIMARY KEY, ADD PRIMARY KEY (`id`); /* id のみ PRI */ 
ALTER TABLE `target_table` CREATE UNIQUE INDEX `IDX_f93ce13306a659c4d4465b58az` ON `target_table` (`yuni`, `kude`, `attehosii`, `kumiawase`); /* ユニークインデックスを貼る */
f93ce13306a659c4d4465b58az は単純に TypeORM が生成したハッシュ値です、実際に適用する時は適当に手元で計算してください。

おしり


著者の画像

ci7lus

@ci7lus

Caramelize - Made withCaramelizeand / Privacy