ジェイウォーク
SQLアンチパターンその1
信 号 無 視
ジェイウォーク
is
単一列に複数の値を格納するSQLアンチパターン
シナリオ
 A「ブログに、共同編集機能付けたいんよ」
 B「はい」
 A「今一人しか編集できないじゃん?」
 B「ですね」
 A「複数人がいじれるように出来ない?」
 B「考えてみます」
シナリオ
 B「今のテーブル定義こんな感じだから」
id title author_id
1 俺のブログ 10000
2 私のブログ 20000
シナリオ
 B「要はauthorをn人に出来ればいい訳で」
id title author_id
1 俺のブログ 10000
2 私のブログ 20000
シナリオ
 B「こうすればいいか」
id title author_id
1 俺のブログ 10000,10001,10002
2 私のブログ 20000,10001,10002
シナリオ
 B「こうすればいいか」
id title author_id
1 俺のブログ 10000,10001,10002
2 私のブログ 20000,10001,10002
信 号 無 視
ジェイウォーク
Bの主張
 既存のテーブル定義でそのまま実現可能で
すしお手軽ですよね
 挿入も文字列連結するだけだし、実装コス
トも低いですしね。
Bの主張
 既存のテーブル定義でそのまま実現可能で
すしお手軽ですよね
 データの妥当性の担保は?
 挿入も文字列連結するだけだし、実装コス
トも低いですしね。
 検索は?更新は?削除は?
ジェイウォーク選択のデメリット
 効率的な検索が出来なくなる
 あるユーザが編集権を持っているブログは?
 あるブログの編集権があるユーザ情報は?
 正規表現?
 パターンマッチ(like)?
 いずれにせよindexが効かなくなる
 → 死
ジェイウォーク選択のデメリット
 更新がつらい
 あるユーザのみ編集権を削除するには?
 参照
 アプリ側でsplit
 削除IDの検索、リストから削除
 再更新
ジェイウォーク選択のデメリット
1,2,3
ジェイウォーク選択のデメリット
1,2,3 1 2 3
split
ジェイウォーク選択のデメリット
1,2,3 1 2 3 1 3
split remove
ジェイウォーク選択のデメリット
1,2,3 1 2 3 1 3 1,2
split remove implode
ジェイウォーク選択のデメリット
1,2,3 1 2 3 1 3 1,2
split remove implode
だるい
ジェイウォーク選択のデメリット
 参照整合性の維持もできないですし。
ジェイウォーク選択のデメリット
 共同編集者の最大人数は何人ですか?
 author_idカラムの定義に依存します!
 varchar(128)に保存できる限り保存できます!
 idが若い(桁数が少ない)と沢山保存できますが
老番(桁数が多い)だとあまり保存できません!
ジェイウォーク選択のデメリット
 まとめ
 参照が死ぬ
 更新が死ぬ
 妥当性検査、参照整合性が死ぬ
 仕様変更で死ぬ
B「僕は…どうしたらよかったんだ…」
解決策
 交差テーブルを使いましょう
 2つのテーブルを参照する外部キーを持つテー
ブルのこと
 blogテーブルとusersテーブルの間にもう一つ
テーブルを作る
解決策
id title
1 俺のブログ
2 私のブログ
blog_id user_id
1 10000
1 10001
1 10002
2 20000
2 10001
2 10002
id name
10000 太郎
10001 一郎
10002 二郎
20000 n郎
これ
PK
blogs usersauthors
解決策 : 交差テーブル
 参照で死なない
 シンプルなクエリ、indexも利用できる
 集約関数も利用できる(countとか)
 更新で死なない
 素直にupdate, insert, deleteするだけ
 妥当性検査、参照整合性で死なない
 カラムの型、外部キー制約
 最大編集人数とかにも変な制約はつかない
 アプリで制約するのもblog_idでcountするだけ
解決策 : 交差テーブル
id title
1 俺のブログ
2 私のブログ
blog_id user_id
1 10000
1 10001
1 10002
2 20000
2 10001
2 10002
id name
10000 太郎
10001 一郎
10002 二郎
20000 n郎
blogs usersauthors
「俺のブログ」の編集者の名前
解決策 : 交差テーブル
id title
1 俺のブログ
2 私のブログ
blog_id user_id
1 10000
1 10001
1 10002
2 20000
2 10001
2 10002
id name
10000 太郎
10001 一郎
10002 二郎
20000 n郎
blogs usersauthors
「一郎」が編集しているブログ
解決策 : 交差テーブル
id title
1 俺のブログ
2 私のブログ
blog_id user_id
1 10000
1 10001
1 10002
2 20000
2 10001
2 10002
id name
10000 太郎
10001 一郎
10002 二郎
20000 n郎
blogs usersauthors
「俺のブログ」から「二郎」を外す
シンプル!
ジェイウォーク(信号無視)
 jaywalk 【自動】〈話〉
 〔交通規則を無視して〕道路を横断する、横断
歩道のないところを横切る
 ◆【語源】jay(不注意な人)から。
 交差点(交差テーブル)を避ける所から命名
 面倒だからと信号無視をせず、交差点を
ちゃんと渡りましょう。
アンチパターンを用いていい場合
 リストの各要素への個別アクセスが存在し
ない、かつパフォーマンスの為にあえて非
正規化を選択する場合
 個別要素へのアクセスがなければ検索性は犠牲
にしても問題ない
 csvが欲しい等の場合、最初からカンマ区切り
にしておいた方が効率が良い
おわり

SQLアンチパターン - ジェイウォーク