126
もう怖くない!? WEBアプリケーションのDB運用

Wtm

Embed Size (px)

DESCRIPTION

第55回「WEB TOUCH MEETING」の発表資料です。

Citation preview

Page 1: Wtm

もう怖くない!?

WEBアプリケーションのDB運用

Page 2: Wtm

What is it?

突然ですが

Page 3: Wtm

What is it?

SQLとかオワコンwww

Page 4: Wtm

What is it?

DBはボトルネックになるから嫌い

Page 5: Wtm

What is it?

データの集計が辛い

Page 6: Wtm

What is it?

そう思ってたりしませんか?

Page 7: Wtm

What is it?

今のシステムにRDBは必要不可欠

Page 8: Wtm

What is it?

だけどRDBの勉強してますか?

Page 9: Wtm

What is it?

じゃあ何時やるか

Page 10: Wtm

What is it?

今でしょ

Page 11: Wtm

What is it?

今でしょ

Page 12: Wtm

What is it?

ということで今日のテーマはコレ

Page 13: Wtm

What is it?

Page 15: Wtm

What is it?

Page 16: Wtm

あじぇんだ

1 自己紹介

2 SQLアンチパターンってなに?

3 リーダブルパスワード

4 インプリシットカラム(暗黙の列)

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

6 まとめ

Page 17: Wtm

あじぇんだ

1 自己紹介

2 SQLアンチパターンってなに?

3 リーダブルパスワード

4 インプリシットカラム(暗黙の列)

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

6 まとめ

Page 18: Wtm

自己紹介

名前:曽根 壮大(そね たけとも)

年齢:28歳(二十代だよ!)

職業:WEB系プログラマー

技術的にはWEB系でLLとかRDBをゴリゴリしてます。

Page 19: Wtm

日本PostgreSQLユーザ会

Twitterは

@soudai1025

と言うアカウントで活動してます。

※技術的なツイートは皆無です。

Page 21: Wtm

自己紹介

オープンセミナー2014@HIROSHIMA

日時 :2014/1月の後半

定員 :100 人(ぐらい

会場 :広島市内

申込 :http://osh-web.github.com/

Page 22: Wtm

あじぇんだ

1 自己紹介

2 SQLアンチパターンってなに?

3 リーダブルパスワード

4 インプリシットカラム(暗黙の列)

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

6 まとめ

Page 23: Wtm

SQLアンチパターンってなに?

諸君は自らの経験からいくらか学ぶことができるという、

全く愚かな考えであろうが、

余はむしろ他人の失敗を学ぶことで、

自分の失敗を回避することを好む。

─オットー・フォン・ビスマルク

Page 24: Wtm

SQLアンチパターンってなに?

失敗例+その解決方法=SQLアンチパターン

Page 25: Wtm

SQLアンチパターンってなに?

つまり、先人の失敗から学ぶ手法(本)

Page 26: Wtm

SQLアンチパターンってなに?

今日はその中から一部をピックアップします

Page 27: Wtm

あじぇんだ

1 自己紹介

2 SQLアンチパターンってなに?

3 リーダブルパスワード

4 インプリシットカラム(暗黙の列)

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

6 まとめ

Page 28: Wtm

リーダブルパスワード

敵はシステムを知っている

クロード・シャノン(数学者)

Page 29: Wtm

リーダブルパスワード

敵はシステムを知っている

クロード・シャノン(数学者)

Page 30: Wtm

リーダブルパスワード

つまりパスワードの扱い

Page 31: Wtm

リーダブルパスワード

例えばパスワードの平文保存

Page 32: Wtm

リーダブルパスワード

これは重大なセキュリティの欠陥

Page 33: Wtm

リーダブルパスワード

じゃあどうすればいいのか

Page 34: Wtm

リーダブルパスワード

暗号化

Page 35: Wtm

リーダブルパスワード

でも暗号化だけじゃない

Page 36: Wtm

リーダブルパスワード

参照

Page 37: Wtm

リーダブルパスワード

つまりはこう

SELECT account FROM kakenavi WHERE password= SHA2(‘deathMaster’, 256)

Page 38: Wtm

リーダブルパスワード

もしSQL文を見られたら?

Page 39: Wtm

リーダブルパスワード

MySQL スロークエリログ

Page 40: Wtm

リーダブルパスワード

PostgreSQL log_statement

Page 41: Wtm

リーダブルパスワード

PHPのエラーログ

Page 42: Wtm

リーダブルパスワード

保存だけでなく参照の仕方も大切

Page 43: Wtm

あじぇんだ

1 自己紹介

2 SQLアンチパターンってなに?

3 リーダブルパスワード

4 インプリシットカラム(暗黙の列)

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

6 まとめ

Page 44: Wtm

インプリシットカラム(暗黙の列)

自分が何を考えているかは、

実際に言葉にしてみるまでわからない

E・M・フォースター(イギリスの小説家)

Page 45: Wtm

インプリシットカラム(暗黙の列)

自分が何を考えているかは、

実際に言葉にしてみるまでわからない

E・M・フォースター(イギリスの小説家)

Page 46: Wtm

インプリシットカラム(暗黙の列)

つまりはこう

SELECT * FROM kakenavi_blog WHERE status = ‘public’

Page 47: Wtm

インプリシットカラム(暗黙の列)

まさかコードの中で*使う人いないよねぇ~

Page 48: Wtm

インプリシットカラム(暗黙の列)

実は結構いる

Page 49: Wtm

インプリシットカラム(暗黙の列)

*を使う街角の人の声

1 columnを書くのがめんどくさい

2 ORM使ったら*になった

3 SQLは短くシンプルにしたい

Page 50: Wtm

インプリシットカラム(暗黙の列)

なぜダメなのか

Page 51: Wtm

インプリシットカラム(暗黙の列)

*がダメな3つの理由

1 予期せぬQueryを招く

2 パフォーマンスの低下

3 DB修正の際のバグの温床

Page 52: Wtm

インプリシットカラム(暗黙の列)

*がダメな3つの理由

1 予期せぬQueryを招く

2 パフォーマンスの低下

3 DB修正の際のバグの温床

Page 53: Wtm

インプリシットカラム(暗黙の列)

予期せぬQueryを招く

SELECT * FROM kakenavi_blog INNER JOIN twitter ON kakenavi_blog.account = twitter.account

Page 54: Wtm

インプリシットカラム(暗黙の列)

もし両方のテーブルに同名のカラムあったら?

Page 55: Wtm

インプリシットカラム(暗黙の列)

プログラム側で間違えるかも…

Page 56: Wtm

インプリシットカラム(暗黙の列)

予期せぬQueryを防ぐには

SELECT kakenavi_blog.id as k_id twitter.id as twitter.t_id FROM kakenavi_blog INNER JOIN twitter ON kakenavi_blog.account = twitter.account

Page 57: Wtm

インプリシットカラム(暗黙の列)

結果を明確にする

Page 58: Wtm

インプリシットカラム(暗黙の列)

想像してみてください

Page 59: Wtm

インプリシットカラム(暗黙の列)

これがGROUP BYだったら・・・

Page 60: Wtm

インプリシットカラム(暗黙の列)

これがサブクエリだったら・・・

Page 61: Wtm

インプリシットカラム(暗黙の列)

結果を明確=列を指定する

Page 62: Wtm

インプリシットカラム(暗黙の列)

*がダメな3つの理由

1 予期せぬQueryを招く

2 パフォーマンスの低下

3 DB修正の際のバグの温床

Page 63: Wtm

インプリシットカラム(暗黙の列)

Page 64: Wtm

インプリシットカラム(暗黙の列)

データの動き

Page 65: Wtm

インプリシットカラム(暗黙の列)

DBサーバ

Id (int)

account (var char)

Blog (txet)

Kakenavi_blog

WEBサーバ

Page 66: Wtm

インプリシットカラム(暗黙の列)

DBサーバ

Id (int)

account (var char)

Blog (txet)

Kakenavi_blog

Network WEBサーバ

Object

Page 67: Wtm

インプリシットカラム(暗黙の列)

DBサーバ

Id (int)

account (var char)

Blog (txet)

Kakenavi_blog

Network WEBサーバ

Object

Page 68: Wtm

インプリシットカラム(暗黙の列)

DBサーバ

Id (int)

account (var cher)

Blog (txet)

Kakenavi_blog

Network WEBサーバ

Object

Page 69: Wtm

インプリシットカラム(暗黙の列)

列を指定してQueryをシェイプアップ!

Page 70: Wtm

インプリシットカラム(暗黙の列)

*がダメな3つの理由

1 予期せぬQueryを招く

2 パフォーマンスの低下

3 DB修正の際のバグの温床

Page 71: Wtm

インプリシットカラム(暗黙の列)

PHP側での処理

$sql = ‘select * from hoge'; $row = $pdo->query($sql)->fetch (); echo $row[‘4’];

Page 72: Wtm

インプリシットカラム(暗黙の列)

もし2列目カラムを消したら?

Page 73: Wtm

インプリシットカラム(暗黙の列)

INSERTの省略記法

--通常 INSERT INTO hoge (hoge_id, deleted, memo) VALUES (NULL, 1, ’hoge’) --省略 INSERT INTO hoge VALUES (NULL, 1, ’hoge’)

Page 74: Wtm

インプリシットカラム(暗黙の列)

もし3列目カラムが無くなったら?

Page 75: Wtm

インプリシットカラム(暗黙の列)

もし3列目カラムが変わったら?

Page 76: Wtm

インプリシットカラム(暗黙の列)

これが SELECT INSET になったら?

Page 77: Wtm

インプリシットカラム(暗黙の列)

誤りを防止する

Page 78: Wtm

インプリシットカラム(暗黙の列)

列は指定する

Page 79: Wtm

あじぇんだ

1 自己紹介

2 SQLアンチパターンってなに?

3 リーダブルパスワード

4 インプリシットカラム(暗黙の列)

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

6 まとめ

Page 80: Wtm

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

お客さん「1ゲーム基本一人だから」

Page 81: Wtm

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

出来たテーブル

Page 82: Wtm

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

一ヶ月後…

Page 83: Wtm

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

お客様「ごめん、キャラやっぱ増やすわ」

Page 84: Wtm

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

お客様「ごめん、キャラやっぱ増やすわ」

Page 85: Wtm

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

さぁどうする?

Page 86: Wtm

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

ピコーン!

Page 87: Wtm

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

カンマ区切り(CSV)でよくね?

Page 88: Wtm

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

ピコーン!カンマ区切りでよくね?

Page 89: Wtm

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

PHP側での処理

$characters = explode(‘,’, $character_column); foreach ( $characters as $key => $character ) { echo $character; }

Page 90: Wtm

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

解決!!

Page 91: Wtm

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

3年後…

Page 92: Wtm

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

お客様「キャラのデータ入らないんだけど」

Page 93: Wtm

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

お客様「キャラのデータ入らないんだけど」

テストでは

Page 94: Wtm

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

なぜか?

Page 95: Wtm

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

カラムの大きさは有限

Page 96: Wtm

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

これがIDだった場合

Page 97: Wtm

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

最初

Page 98: Wtm

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

10,11,12,13,14,15

Page 99: Wtm

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

3年後

Page 100: Wtm

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

1000010, 1000011, 1000012

Page 101: Wtm

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

限界が来ると拡張が難しい

Page 102: Wtm

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

CSV以外にもJSONやXMLでも…

Page 103: Wtm

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

ではどうすれば良かったか

Page 104: Wtm

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

リレーションする

Page 105: Wtm

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

これでレコードの限界まで大丈夫

Page 106: Wtm

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

他にもこんな問題が

Page 107: Wtm

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

問題点

1 検索の低パフォーマンス

2 更新時の整合性が担保できない

3 集約クエリが作成出来ない

Page 108: Wtm

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

リレーションすれば

Page 109: Wtm

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

メリット

1 検索時にINDEXが効く

2 整合性が担保できる

3 集約クエリによる集計の簡略化

Page 110: Wtm

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

正規化大事

Page 111: Wtm

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

他の解決策

Page 112: Wtm

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

PostgreSQLの柔軟な型

Page 113: Wtm

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

柔軟な型

1 Array型で持てる

2 XMLも持てる

3 JOSNでも持てる←New

Page 114: Wtm

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

Indexも集計も絞り込みも思いのまま!

Page 115: Wtm

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

だたしORMとかほぼ全滅

Page 116: Wtm

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

PostgreSQL依存なので移行はしにくい

Page 117: Wtm

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

なので基本は正規化

Page 118: Wtm

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

仕様は変わる

Page 119: Wtm

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

それを受け止める柔軟性が大切

Page 120: Wtm

あじぇんだ

1 自己紹介

2 SQLアンチパターンってなに?

3 リーダブルパスワード

4 インプリシットカラム(暗黙の列)

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

6 まとめ

Page 121: Wtm

まとめ

アンチパターンとは先人の知恵である

Page 122: Wtm

まとめ

愚者は経験に学び、賢者は歴史に学ぶ

Page 123: Wtm

まとめ

アンチパターンを知るメリット

1 この問題!進研ゼミでやったところだ!

Page 124: Wtm

まとめ

アンチパターンを知るメリット

1 この問題!進研ゼミでやったところだ!

2 悪いことを「悪い」と知れる

Page 125: Wtm

まとめ

アンチパターンを知るメリット

1 この問題!進研ゼミでやったところだ!

2 悪いことを「悪い」と知れる

3 失敗談は鉄板ネタになる←いまここ

Page 126: Wtm

まとめ

みなさんも仲間と失敗談を共有しましょう!