30
ジェイウォーク SQLアンチパターンその1

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

Embed Size (px)

DESCRIPTION

社内勉強会資料

Citation preview

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

ジェイウォーク

SQLアンチパターンその1 信 号 無 視

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

ジェイウォーク is

単一列に複数の値を格納するSQLアンチパターン

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

シナリオ

A「ブログに、共同編集機能付けたいんよ」

B「はい」

A「今一人しか編集できないじゃん?」

B「ですね」

A「複数人がいじれるように出来ない?」

B「考えてみます」

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

シナリオ

B「今のテーブル定義こんな感じだから」

id title author_id

1 俺のブログ 10000

2 私のブログ 20000

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

シナリオ

B「要はauthorをn人に出来ればいい訳で」

id title author_id

1 俺のブログ 10000

2 私のブログ 20000

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

シナリオ

B「こうすればいいか」

id title author_id

1 俺のブログ 10000,10001,10002

2 私のブログ 20000,10001,10002

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

シナリオ

B「こうすればいいか」

id title author_id

1 俺のブログ 10000,10001,10002

2 私のブログ 20000,10001,10002

信 号 無 視

ジェイウォーク

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

Bの主張

既存のテーブル定義でそのまま実現可能ですしお手軽ですよね

挿入も文字列連結するだけだし、実装コストも低いですしね。

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

Bの主張

既存のテーブル定義でそのまま実現可能ですしお手軽ですよね

データの妥当性の担保は?

挿入も文字列連結するだけだし、実装コストも低いですしね。

検索は?更新は?削除は?

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

ジェイウォーク選択のデメリット

効率的な検索が出来なくなる

あるユーザが編集権を持っているブログは?

あるブログの編集権があるユーザ情報は?

正規表現?

パターンマッチ(like)?

いずれにせよindexが効かなくなる

→ 死

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

ジェイウォーク選択のデメリット

更新がつらい

あるユーザのみ編集権を削除するには?

参照

アプリ側でsplit

削除IDの検索、リストから削除

再更新

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

ジェイウォーク選択のデメリット

1,2,3

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

ジェイウォーク選択のデメリット

1,2,3 1 2 3

split

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

ジェイウォーク選択のデメリット

1,2,3 1 2 3 1 3

split remove

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

ジェイウォーク選択のデメリット

1,2,3 1 2 3 1 3 1,2

split remove implode

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

ジェイウォーク選択のデメリット

1,2,3 1 2 3 1 3 1,2

split remove implode

だるい

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

ジェイウォーク選択のデメリット

参照整合性の維持もできないですし。

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

ジェイウォーク選択のデメリット

共同編集者の最大人数は何人ですか?

author_idカラムの定義に依存します!

varchar(128)に保存できる限り保存できます!

idが若い(桁数が少ない)と沢山保存できますが

老番(桁数が多い)だとあまり保存できません!

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

ジェイウォーク選択のデメリット

まとめ

参照が死ぬ

更新が死ぬ

妥当性検査、参照整合性が死ぬ

仕様変更で死ぬ

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

B「僕は…どうしたらよかったんだ…」

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

解決策

交差テーブルを使いましょう

2つのテーブルを参照する外部キーを持つテーブルのこと

blogテーブルとusersテーブルの間にもう一つテーブルを作る

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

解決策

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 users authors

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

解決策 : 交差テーブル

参照で死なない

シンプルなクエリ、indexも利用できる

集約関数も利用できる(countとか)

更新で死なない

素直にupdate, insert, deleteするだけ

妥当性検査、参照整合性で死なない

カラムの型、外部キー制約

最大編集人数とかにも変な制約はつかない

アプリで制約するのもblog_idでcountするだけ

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

解決策 : 交差テーブル

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 users authors

「俺のブログ」の編集者の名前

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

解決策 : 交差テーブル

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 users authors

「一郎」が編集しているブログ

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

解決策 : 交差テーブル

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 users authors

「俺のブログ」から「二郎」を外す

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

シンプル!

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

ジェイウォーク(信号無視)

jaywalk 【自動】〈話〉

〔交通規則を無視して〕道路を横断する、横断歩道のないところを横切る

◆【語源】jay(不注意な人)から。

交差点(交差テーブル)を避ける所から命名

面倒だからと信号無視をせず、交差点をちゃんと渡りましょう。

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

アンチパターンを用いていい場合

リストの各要素への個別アクセスが存在しない、かつパフォーマンスの為にあえて非正規化を選択する場合

個別要素へのアクセスがなければ検索性は犠牲にしても問題ない

csvが欲しい等の場合、最初からカンマ区切りにしておいた方が効率が良い

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

おわり