Wtm

Preview:

DESCRIPTION

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

Citation preview

もう怖くない!?

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

What is it?

突然ですが

What is it?

SQLとかオワコンwww

What is it?

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

What is it?

データの集計が辛い

What is it?

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

What is it?

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

What is it?

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

What is it?

じゃあ何時やるか

What is it?

今でしょ

What is it?

今でしょ

What is it?

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

What is it?

What is it?

あじぇんだ

1 自己紹介

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

3 リーダブルパスワード

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

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

6 まとめ

あじぇんだ

1 自己紹介

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

3 リーダブルパスワード

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

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

6 まとめ

自己紹介

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

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

職業:WEB系プログラマー

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

日本PostgreSQLユーザ会

Twitterは

@soudai1025

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

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

自己紹介

オープンセミナー2014@HIROSHIMA

日時 :2014/1月の後半

定員 :100 人(ぐらい

会場 :広島市内

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

あじぇんだ

1 自己紹介

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

3 リーダブルパスワード

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

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

6 まとめ

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

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

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

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

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

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

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

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

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

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

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

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

あじぇんだ

1 自己紹介

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

3 リーダブルパスワード

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

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

6 まとめ

リーダブルパスワード

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

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

リーダブルパスワード

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

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

リーダブルパスワード

つまりパスワードの扱い

リーダブルパスワード

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

リーダブルパスワード

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

リーダブルパスワード

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

リーダブルパスワード

暗号化

リーダブルパスワード

でも暗号化だけじゃない

リーダブルパスワード

参照

リーダブルパスワード

つまりはこう

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

リーダブルパスワード

もしSQL文を見られたら?

リーダブルパスワード

MySQL スロークエリログ

リーダブルパスワード

PostgreSQL log_statement

リーダブルパスワード

PHPのエラーログ

リーダブルパスワード

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

あじぇんだ

1 自己紹介

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

3 リーダブルパスワード

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

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

6 まとめ

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

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

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

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

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

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

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

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

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

つまりはこう

SELECT * FROM kakenavi_blog WHERE status = ‘public’

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

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

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

実は結構いる

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

*を使う街角の人の声

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

2 ORM使ったら*になった

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

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

なぜダメなのか

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

*がダメな3つの理由

1 予期せぬQueryを招く

2 パフォーマンスの低下

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

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

*がダメな3つの理由

1 予期せぬQueryを招く

2 パフォーマンスの低下

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

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

予期せぬQueryを招く

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

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

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

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

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

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

予期せぬ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

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

結果を明確にする

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

想像してみてください

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

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

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

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

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

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

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

*がダメな3つの理由

1 予期せぬQueryを招く

2 パフォーマンスの低下

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

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

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

データの動き

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

DBサーバ

Id (int)

account (var char)

Blog (txet)

Kakenavi_blog

WEBサーバ

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

DBサーバ

Id (int)

account (var char)

Blog (txet)

Kakenavi_blog

Network WEBサーバ

Object

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

DBサーバ

Id (int)

account (var char)

Blog (txet)

Kakenavi_blog

Network WEBサーバ

Object

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

DBサーバ

Id (int)

account (var cher)

Blog (txet)

Kakenavi_blog

Network WEBサーバ

Object

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

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

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

*がダメな3つの理由

1 予期せぬQueryを招く

2 パフォーマンスの低下

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

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

PHP側での処理

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

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

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

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

INSERTの省略記法

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

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

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

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

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

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

これが SELECT INSET になったら?

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

誤りを防止する

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

列は指定する

あじぇんだ

1 自己紹介

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

3 リーダブルパスワード

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

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

6 まとめ

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

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

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

出来たテーブル

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

一ヶ月後…

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

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

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

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

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

さぁどうする?

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

ピコーン!

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

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

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

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

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

PHP側での処理

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

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

解決!!

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

3年後…

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

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

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

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

テストでは

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

なぜか?

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

カラムの大きさは有限

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

これがIDだった場合

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

最初

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

10,11,12,13,14,15

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

3年後

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

1000010, 1000011, 1000012

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

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

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

CSV以外にもJSONやXMLでも…

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

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

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

リレーションする

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

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

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

他にもこんな問題が

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

問題点

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

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

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

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

リレーションすれば

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

メリット

1 検索時にINDEXが効く

2 整合性が担保できる

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

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

正規化大事

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

他の解決策

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

PostgreSQLの柔軟な型

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

柔軟な型

1 Array型で持てる

2 XMLも持てる

3 JOSNでも持てる←New

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

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

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

だたしORMとかほぼ全滅

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

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

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

なので基本は正規化

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

仕様は変わる

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

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

あじぇんだ

1 自己紹介

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

3 リーダブルパスワード

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

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

6 まとめ

まとめ

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

まとめ

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

まとめ

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

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

まとめ

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

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

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

まとめ

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

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

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

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

まとめ

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