196
PostgreSQLアンチパターン

PostgreSQLアンチパターン

Embed Size (px)

Citation preview

Page 1: PostgreSQLアンチパターン

PostgreSQLアンチパターン

Page 2: PostgreSQLアンチパターン

What is it?

RDBの限界を感じた事ありませんか?

Page 3: PostgreSQLアンチパターン

What is it?

PostgreSQLは銀の弾丸ではありません

Page 4: PostgreSQLアンチパターン

What is it?

アンチパターン

Page 5: PostgreSQLアンチパターン

What is it?

アンチパターン ↓

良かれと思ってした事が後々に苦しみを生む

Page 6: PostgreSQLアンチパターン

What is it?

アンチパターンを知る

Page 7: PostgreSQLアンチパターン

What is it?

アンチパターンを知る ↓

同じ過ちを繰り返さない

Page 8: PostgreSQLアンチパターン

What is it?

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

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

Page 9: PostgreSQLアンチパターン

What is it?

Page 10: PostgreSQLアンチパターン

What is it?

SQLアンチパターンは厳選された失敗集

Page 11: PostgreSQLアンチパターン

What is it?

SQLアンチパターンは厳選された失敗集

↓ DBのノウハウが詰まった名著

Page 12: PostgreSQLアンチパターン

What is it?

しかしMySQLがベース

Page 13: PostgreSQLアンチパターン

What is it?

今日はPostgreSQLの失敗例をご紹介します

Page 14: PostgreSQLアンチパターン

What is it?

SQLアンチパターン本の内容

とは全く関係ありません

Page 15: PostgreSQLアンチパターン

What is it?

俺の屍を越えて行け

Page 16: PostgreSQLアンチパターン

あじぇんだ

1 自己紹介 2 とりあえず削除フラグ 3 困ったときの配列型とJSON型 4 マテビューの功罪 5 まとめ

Page 17: PostgreSQLアンチパターン

あじぇんだ

1 自己紹介 2 とりあえず削除フラグ 3 困ったときの配列型とJSON型 4 マテビューの功罪 5 まとめ

Page 18: PostgreSQLアンチパターン

自己紹介名前:曽根 壮大(そね たけとも) 年齢:31歳(三人の子供がいます) 職業:Webエンジニア

所属:日本PostgreSQLユーザ会

   中国支部 支部長

  技術的にはLL系言語とかRDBが好きです

Page 19: PostgreSQLアンチパターン

中国地方DB勉強会

https://dbstudychugoku.github.io/

Page 20: PostgreSQLアンチパターン

あじぇんだ

1 自己紹介 2 とりあえず削除フラグ 3 困ったときの配列型とJSON型 4 マテビューの功罪 5 まとめ

Page 21: PostgreSQLアンチパターン

とりあえず削除フラグ

http://www.slideshare.net/t_wada/ronsakucasual

Page 22: PostgreSQLアンチパターン

とりあえず削除フラグ

こんなカラム名を

作ったことありませんか?

Page 23: PostgreSQLアンチパターン

とりあえず削除フラグ

hoge_delete_flag

Page 24: PostgreSQLアンチパターン

とりあえず削除フラグ

会員削除フラグ… 顧客削除フラグ…

hogeデータ削除フラグ…

Page 25: PostgreSQLアンチパターン

とりあえず削除フラグ

論理削除と言う名の闇

Page 26: PostgreSQLアンチパターン

とりあえず削除フラグ

Page 27: PostgreSQLアンチパターン

とりあえず削除フラグ

論理削除はなぜダメなのか?

Page 28: PostgreSQLアンチパターン

とりあえず削除フラグ

論理削除の理由

Page 29: PostgreSQLアンチパターン

とりあえず削除フラグ

• エンドユーザから見えなくしたいがデータは消したくない • 削除したデータを検索したい • データを消さずにログに残したい • 誤った操作をなかったことにしたい、直ぐに元に戻したい

Page 30: PostgreSQLアンチパターン

とりあえず削除フラグ

そして生まれるDELETE_FLAG

Page 31: PostgreSQLアンチパターン

とりあえず削除フラグ

論理削除のデメリット

Page 32: PostgreSQLアンチパターン

とりあえず削除フラグ

• 積み重なるWHERE delete_flag = 0 • Unique制約が使えなくなる • 複雑な表示条件(Query)の原因

Page 33: PostgreSQLアンチパターン

とりあえず削除フラグ

• 積み重なるWHERE delete_flag = 0 • Unique制約が使えなくなる • 複雑な表示条件(Query)の原因

Page 34: PostgreSQLアンチパターン

積み重なるWHERE句

-- ブログを取ってきたい場合 SELECT * FROM blog WHERE blog.delete_flag = 0

Page 35: PostgreSQLアンチパターン

積み重なるWHERE句

-- ブログを取ってきたい場合 SELECT * FROM blog WHERE blog.delete_flag = 0

ブログの削除フラグを見る

Page 36: PostgreSQLアンチパターン

積み重なるWHERE句

-- ブログを取ってきたい場合 SELECT * FROM blog WHERE blog.delete_flag = 0

ブログの削除フラグを見る

更新者アカウントが削除されてたら?

Page 37: PostgreSQLアンチパターン

積み重なるWHERE句

-- 有効なアカウントのブログを取ってきたい場合 SELECT * FROM blog INNER JOIN users ON users.id = blog.user_id AND users.delete_flag = 0 WHERE blog.delete_flag = 0

Page 38: PostgreSQLアンチパターン

積み重なるWHERE句

-- 有効なアカウントのブログを取ってきたい場合 SELECT * FROM blog INNER JOIN users ON users.id = blog.user_id AND users.delete_flag = 0 WHERE blog.delete_flag = 0

ユーザの削除フラグを見る

Page 39: PostgreSQLアンチパターン

積み重なるWHERE句

-- 有効なアカウントのブログを取ってきたい場合 SELECT * FROM blog INNER JOIN users ON users.id = blog.user_id AND users.delete_flag = 0 WHERE blog.delete_flag = 0

ユーザの削除フラグを見る

所属が削除されてたら?

Page 40: PostgreSQLアンチパターン

積み重なるWHERE句

-- 有効な所属の有効なアカウントのブログを取ってきたい場合 SELECT * FROM blog INNER JOIN users ON users.id = blog.user_id AND users.delete_flag = 0 INNER JOIN customers ON customers.id = users.customer_id AND customers.delete_flag = 0 WHERE blog.delete_flag = 0

Page 41: PostgreSQLアンチパターン

積み重なるWHERE句

-- 有効な所属の有効なアカウントのブログを取ってきたい場合 SELECT * FROM blog INNER JOIN users ON users.id = blog.user_id AND users.delete_flag = 0 INNER JOIN customers ON customers.id = users.customer_id AND customers.delete_flag = 0 WHERE blog.delete_flag = 0

JOINがどんどん積み重なる

Page 42: PostgreSQLアンチパターン

積み重なるWHERE句

-- 有効な所属の有効なアカウントのブログを取ってきたい場合 SELECT * FROM blog INNER JOIN users ON users.id = blog.user_id AND users.delete_flag = 0 INNER JOIN customers ON customers.id = users.customer_id AND customers.delete_flag = 0 WHERE blog.delete_flag = 0

JOINがどんどん積み重なる

Queryがボトルネックに

Page 43: PostgreSQLアンチパターン

とりあえず削除フラグ

Queryの複雑度に対する対策

Page 44: PostgreSQLアンチパターン

とりあえず削除フラグ

Queryの複雑度に対する対策 ↓

有効なデータのViewを作る

Page 45: PostgreSQLアンチパターン

とりあえず削除フラグ

Queryの複雑度に対する対策 ↓

有効なデータのViewを作るQueryの高速化にはならない

Page 46: PostgreSQLアンチパターン

とりあえず削除フラグ

全てのINDEXのセカンダリに

DELETE_FLAGを入れる必要がある

Page 47: PostgreSQLアンチパターン

とりあえず削除フラグ

全てのINDEXのセカンダリに

DELETE_FLAGを入れる必要がある

INDEXの肥大化よりも そもそもINDEXを効かせる 複数のQueryを書くのが大変

Page 48: PostgreSQLアンチパターン

とりあえず削除フラグ

PostgreSQLには

マテリアライズド・ビューがある

Page 49: PostgreSQLアンチパターン

とりあえず削除フラグ

マテビューで有効データViewを作る

Page 50: PostgreSQLアンチパターン

とりあえず削除フラグ

マテビューで有効データViewを作る ↓

高速でQueryもシンプル

Page 51: PostgreSQLアンチパターン

とりあえず削除フラグ

マテビューで有効データViewを作る ↓

高速でQueryもシンプルSELECT * FROM active_blog

Page 52: PostgreSQLアンチパターン

とりあえず削除フラグ

それ、シンプルになるの参照だけ

Page 53: PostgreSQLアンチパターン

とりあえず削除フラグ

それ、シンプルになるの参照だけ ↓

更新系で生まれる悪夢

Page 54: PostgreSQLアンチパターン

とりあえず削除フラグ

更新したらマテビューを更新

Page 55: PostgreSQLアンチパターン

とりあえず削除フラグ

更新したらマテビューを更新 ↓

customersでもusersでもblogでも 更新があればマテビューも更新

Page 56: PostgreSQLアンチパターン

とりあえず削除フラグ

更新したらマテビューを更新 ↓

customersでもusersでもblogでも 更新があればマテビューも更新

頻発する REFRESH MATERIALIZED VIEW

Page 57: PostgreSQLアンチパターン

とりあえず削除フラグ

実際にはdeleteされないので データは増え続ける

Page 58: PostgreSQLアンチパターン

とりあえず削除フラグ

実際にはdeleteされないので データは増え続ける

↓ マテビューの更新コストが肥大

Page 59: PostgreSQLアンチパターン

とりあえず削除フラグ

実際にはdeleteされないので データは増え続ける

↓ マテビューの更新コストが肥大

そして第三章の問題へ…

Page 60: PostgreSQLアンチパターン

とりあえず削除フラグ

• 積み重なるWHERE delete_flag = 0 • Unique制約が使えなくなる • 複雑な表示条件(Query)の原因

Page 61: PostgreSQLアンチパターン

とりあえず削除フラグ

• 積み重なるWHERE delete_flag = 0 • Unique制約が使えなくなる • 複雑な表示条件(Query)の原因

つまり外部Key制約も死ぬ

Page 62: PostgreSQLアンチパターン

とりあえず削除フラグ

id name age deleted

1 soudai 30 1

2 soudai 30 0

3 sone 20 0

4 taketomo 31 0

Page 63: PostgreSQLアンチパターン

とりあえず削除フラグ

id name age deleted

1 soudai 30 1

2 soudai 30 0

3 sone 20 0

4 taketomo 31 0

Page 64: PostgreSQLアンチパターン

とりあえず削除フラグ

id name age deleted

1 soudai 30 1

2 soudai 30 0

3 sone 20 0

4 taketomo 31 0

同じユーザが2名いるのでUnique制約できない

Page 65: PostgreSQLアンチパターン

とりあえず削除フラグ

id name age deleted

1 soudai 30 1

2 soudai 30 0

3 sone 20 0

4 taketomo 31 0

同じユーザが2名いるのでUnique制約できない

もちろん外部キー制約もできない

Page 66: PostgreSQLアンチパターン

とりあえず削除フラグ

id name age deleted

1 soudai 30 1

2 soudai 30 0

3 sone 20 0

4 taketomo 31 0

サロゲートキーで外部キー制約した場合は 関連したデータは別人扱いになる

Page 67: PostgreSQLアンチパターン

とりあえず削除フラグ

id name age deleted

1 soudai 30 1

2 soudai 30 0

3 sone 20 0

4 taketomo 31 0

サロゲートキーで外部キー制約した場合は 関連したデータは別人扱いになる

ナチュラルキーの場合は死ぬ

Page 68: PostgreSQLアンチパターン

とりあえず削除フラグ

PostgreSQLには

Unique制約にWHERE句がある

Page 69: PostgreSQLアンチパターン

Unique制約が使えなくなる

-- deletedが0の時にUnique制約をかける CREATE UNIQUE INDEX user_idx ON users (name) WHERE deleted = 0;

Page 70: PostgreSQLアンチパターン

とりあえず削除フラグ

id name age deleted

1 soudai 30 1

2 soudai 30 0

3 sone 20 0

4 taketomo 31 0

Page 71: PostgreSQLアンチパターン

とりあえず削除フラグ

id name age deleted

1 soudai 30 1

2 soudai 30 0

3 sone 20 0

4 taketomo 31 0

Page 72: PostgreSQLアンチパターン

とりあえず削除フラグ

id name age deleted

1 soudai 30 1

2 soudai 30 0

3 sone 20 0

4 taketomo 31 0

Page 73: PostgreSQLアンチパターン

とりあえず削除フラグ

id name age deleted

1 soudai 30 1

2 soudai 30 0

3 sone 20 0

4 taketomo 31 0

deletedが1なのでUnique制約対象外

Page 74: PostgreSQLアンチパターン

とりあえず削除フラグ

id name age deleted

1 soudai 30 1

2 soudai 30 0

3 sone 20 0

4 taketomo 31 0

nameでUnique制約をかけれる

Page 75: PostgreSQLアンチパターン

とりあえず削除フラグ

id name age deleted

1 soudai 30 1

2 soudai 30 0

3 sone 20 0

4 taketomo 31 0

nameでUnique制約をかけれる

しかし外部キー制約は死ぬ

Page 76: PostgreSQLアンチパターン

とりあえず削除フラグ

Unique制約にWHERE句 ↓

結局は外部キー制約は死ぬ

Page 77: PostgreSQLアンチパターン

とりあえず削除フラグ

外部キー制約が死ぬ

Page 78: PostgreSQLアンチパターン

とりあえず削除フラグ

外部キー制約が死ぬ ↓

テーブルの関連性の担保が死ぬ

Page 79: PostgreSQLアンチパターン

とりあえず削除フラグ

データの不整合を防げない

Page 80: PostgreSQLアンチパターン

とりあえず削除フラグ

データの不整合を防げない ↓

バグの温床になる

Page 81: PostgreSQLアンチパターン

とりあえず削除フラグ

• 積み重なるWHERE delete_flag = 0 • Unique制約が使えなくなる • 複雑な表示条件(Query)の原因

Page 82: PostgreSQLアンチパターン

とりあえず削除フラグ

正しいデータを

表示させる条件が多い

Page 83: PostgreSQLアンチパターン

積み重なるWHERE句

-- 有効な所属の有効なアカウントのブログを取ってきたい場合 SELECT * FROM blog INNER JOIN users ON users.id = blog.user_id AND users.delete_flag = 0 INNER JOIN customers ON customers.id = users.customer_id AND customers.delete_flag = 0 WHERE blog.delete_flag = 0

表示させるために 3つのテーブルが関係している

Page 84: PostgreSQLアンチパターン

とりあえず削除フラグ

1つのデータを取るために

関係するTABLEが多すぎる

Page 85: PostgreSQLアンチパターン

とりあえず削除フラグ

「あのデータ取るには○○と☓☓と△△をJOINしてWHEREしてSELECT

句にASで別名を付けて…」 みたいな事が頻発する

Page 86: PostgreSQLアンチパターン

とりあえず削除フラグ

仕様変更の時の影響範囲が広い

Page 87: PostgreSQLアンチパターン

とりあえず削除フラグ

仕様変更の時の影響範囲が広い ↓

つまりバグの温床になる

Page 88: PostgreSQLアンチパターン

とりあえず削除フラグ

論理削除は使わないほうが良い

Page 89: PostgreSQLアンチパターン

とりあえず削除フラグ

論理削除は使わないほうが良い ↓

TABLEに状態を持たせない

Page 90: PostgreSQLアンチパターン

とりあえず削除フラグ

論理削除は使わないほうが良い ↓

TABLEに状態を持たせない

リレーショナルモデルで表現する

Page 91: PostgreSQLアンチパターン

とりあえず削除フラグ

処方箋

Page 92: PostgreSQLアンチパターン

とりあえず削除フラグ

有効なデータのみを残す

Page 93: PostgreSQLアンチパターン

とりあえず削除フラグ

有効なデータのみを残す ↓

例えば削除済みTABLEを作る

Page 94: PostgreSQLアンチパターン

とりあえず削除フラグ

deleted_usersusers

Page 95: PostgreSQLアンチパターン

とりあえず削除フラグ

deleted_usersusers

soudai

sone

taketomo

Page 96: PostgreSQLアンチパターン

とりあえず削除フラグ

deleted_usersusers

soudai

sone

taketomo

削除(DELETE文)

Page 97: PostgreSQLアンチパターン

とりあえず削除フラグ

deleted_usersusers

soudai

sone

taketomo

soudai

トリガーで移す

Page 98: PostgreSQLアンチパターン

とりあえず削除フラグ

deleted_usersusers

sone

taketomo

soudai

テーブルには実際のデータのみが残る

Page 99: PostgreSQLアンチパターン

とりあえず削除フラグ

注意点

Page 100: PostgreSQLアンチパターン

とりあえず削除フラグ

注意点 ↓

トリガーは仕様変更に弱い

Page 101: PostgreSQLアンチパターン

とりあえず削除フラグ

注意点 ↓

トリガーは仕様変更に弱い

例えばALTER文でカラムを増やすと トリガーが死ぬ

Page 102: PostgreSQLアンチパターン

とりあえず削除フラグ

ケースバイケースで手法は選ぶこと

Page 103: PostgreSQLアンチパターン

とりあえず削除フラグ

ケースバイケースで手法は選ぶこと ↓

論理削除は使わない

Page 104: PostgreSQLアンチパターン

とりあえず削除フラグ

関連したテーブルは?

Page 105: PostgreSQLアンチパターン

とりあえず削除フラグ

関連したテーブルは? ↓

必要なら削除済みTABLEを作る 不要ならDELETEする

Page 106: PostgreSQLアンチパターン

とりあえず削除フラグ

関連したテーブルは? ↓

必要なら削除済みTABLEを作る 不要ならDELETEする

外部キー制約が使えればCASCADEも出来る

Page 107: PostgreSQLアンチパターン

とりあえず削除フラグ

関連したテーブルは? ↓

必要なら削除済みTABLEを作る 不要ならDELETEする

外部キー制約が使えればCASCADEも出来る

事実のみを保存する

Page 108: PostgreSQLアンチパターン

とりあえず削除フラグ

•ユーザの状態(statusカラム) •課金状態(与信、請求済み) •カート情報(カゴの中、購入済み)

類似例

Page 109: PostgreSQLアンチパターン

とりあえず削除フラグ

DBに状態を持たせるのは危ない

Page 110: PostgreSQLアンチパターン

とりあえず削除フラグ

DBに状態を持たせるのは危ない ↓

DBには事実のみを保存する

Page 111: PostgreSQLアンチパターン

あじぇんだ

1 自己紹介 2 とりあえず削除フラグ 3 困ったときの配列型とJSON型 4 マテビューの功罪 5 まとめ

Page 112: PostgreSQLアンチパターン

困ったときの配列型とJSON型

PostgreSQLは型が豊富

Page 113: PostgreSQLアンチパターン

困ったときの配列型とJSON型

配列型やJSON型を使うと

Page 114: PostgreSQLアンチパターン

困ったときの配列型とJSON型

配列型やJSON型を使うと ↓

1:Nを1つのカラムで表現出来る

Page 115: PostgreSQLアンチパターン

困ったときの配列型とJSON型

id title body

1 初めてのポスグレ …

2pg9.5 beta リリース …

3篠崎愛

「おしのブログ」 …

blog_id tag

1 postgres1 beginner3 魂

blog tag

Page 116: PostgreSQLアンチパターン

困ったときの配列型とJSON型

id title body

1 初めてのポスグレ …

2pg9.5 beta リリース …

3篠崎愛

「おしのブログ」 …

blog_id tag

1 postgres1 beginner3 魂

blog tag

1:N

Page 117: PostgreSQLアンチパターン

困ったときの配列型とJSON型

id title body tag

1 初めてのポスグレ … [“postgres”, ”beginner”]

2pg9.5 beta リリース … null

3篠崎愛

「おしのブログ」 … [“魂”]

blog(配列型の使用例)

Page 118: PostgreSQLアンチパターン

困ったときの配列型とJSON型

テーブルを減らす事が出来る

Page 119: PostgreSQLアンチパターン

困ったときの配列型とJSON型

テーブルを減らす事が出来る ↓

しかもINDEXも効く

Page 120: PostgreSQLアンチパターン

困ったときの配列型とJSON型

JSON型の場合

Page 121: PostgreSQLアンチパターン

困ったときの配列型とJSON型

JSON型の場合 ↓

KeyValueを表現できる

Page 122: PostgreSQLアンチパターン

困ったときの配列型とJSON型

id title body properties

1 初めてのポスグレ … {tag:[“postgres”, “beginner”]}

2 pg9.5 beta リリース

… null

3 篠崎愛 「おしのブログ」

… {tag:[“魂”]}

blog(JSON型の使用例)

Page 123: PostgreSQLアンチパターン

困ったときの配列型とJSON型

id title body properties

1 初めてのポスグレ … {tag:[“postgres”, “beginner”]}

2 pg9.5 beta リリース

… null

3 篠崎愛 「おしのブログ」

… {tag:[“魂”], event:[“握手会”]}

blog(JSON型の使用例)

Page 124: PostgreSQLアンチパターン

困ったときの配列型とJSON型

id title body properties

1 初めてのポスグレ … {tag:[“postgres”, “beginner”]}

2 pg9.5 beta リリース

… null

3 篠崎愛 「おしのブログ」

… {tag:[“魂”], event:[“握手会”]}

blog(JSON型の使用例)

JSON型はドキュメント指向なスキーマレスを表現できる→つまりDB構造を変更すること無く項目を追加できる

Page 125: PostgreSQLアンチパターン

とりあえず削除フラグ

注意点 ↓

トリガーは仕様変更に弱い

例えばALTER文でカラムを増やすと トリガーが死ぬ

Page 126: PostgreSQLアンチパターン

とりあえず削除フラグ

注意点 ↓

トリガーは仕様変更に弱い

例えばALTER文でカラムを増やすと トリガーが死ぬ

JSON型ならDB構造を変えない →仕様変更時にトリガーが死なない

Page 127: PostgreSQLアンチパターン

困ったときの配列型とJSON型

JSON型はデータに柔軟性を与える

Page 128: PostgreSQLアンチパターン

困ったときの配列型とJSON型

JSON型はデータに柔軟性を与える ↓

それは整合性を犠牲にする

Page 129: PostgreSQLアンチパターン

困ったときの配列型とJSON型

配列型もJSON型も

データを守る機能が弱い

Page 130: PostgreSQLアンチパターン

困ったときの配列型とJSON型

外部キー制約→使えない CHECK制約→使えない

Page 131: PostgreSQLアンチパターン

困ったときの配列型とJSON型

外部キー制約→使えない CHECK制約→使えない

該当のカラムが 紐づくテーブルを関連付けなれない

Page 132: PostgreSQLアンチパターン

困ったときの配列型とJSON型

外部キー制約→使えない CHECK制約→使えない

該当のカラムに 入るデータを制限出来ない

Page 133: PostgreSQLアンチパターン

困ったときの配列型とJSON型

UPDATE文に弱い

Page 134: PostgreSQLアンチパターン

困ったときの配列型とJSON型

UPDATE文に弱い ↓

特定の要素のみの更新が難しい

Page 135: PostgreSQLアンチパターン

困ったときの配列型とJSON型

仕様が曖昧な時にJSON型

Page 136: PostgreSQLアンチパターン

困ったときの配列型とJSON型

仕様が曖昧な時にJSON型 ↓

仕様変更には強いので有効だが 運用時にデータが守れない

Page 137: PostgreSQLアンチパターン

困ったときの配列型とJSON型

処方箋

Page 138: PostgreSQLアンチパターン

困ったときの配列型とJSON型

ちゃんと正規化する

Page 139: PostgreSQLアンチパターン

困ったときの配列型とJSON型

ちゃんと正規化する ↓

面倒でも正規化すれば 運用フェーズで必ず救われる

Page 140: PostgreSQLアンチパターン

困ったときの配列型とJSON型

ちゃんと正規化する ↓

面倒でも正規化すれば 運用フェーズで必ず救われる

逆説的にリソースが許されるなら 困ってから正規化の選択肢もアリ

Page 141: PostgreSQLアンチパターン

困ったときの配列型とJSON型

使っていい場合

Page 142: PostgreSQLアンチパターン

困ったときの配列型とJSON型

• UPDATEが無い(INSERTのみ) • データを守る必要が無い(制約を使わない) • データを関連付けない(JOINしない) • UPDETE時は対象カラムをまるっと更新 • 集約関数等の対象にならない

Page 143: PostgreSQLアンチパターン

困ったときの配列型とJSON型

•ブログのTags •可変なプロパティ •外部のWebAPIの結果

具体例

Page 144: PostgreSQLアンチパターン

困ったときの配列型とJSON型

•ブログのTags •可変なプロパティ •外部のWebAPIの結果

具体例例えばServerのOS情報などは ディストリビューションの違いを 気にしなくても良くなる

Page 145: PostgreSQLアンチパターン

困ったときの配列型とJSON型

•ブログのTags •可変なプロパティ •外部のWebAPIの結果

具体例

いつ仕様変更が来るかわからない →その変更に柔軟に対応できる

Page 146: PostgreSQLアンチパターン

困ったときの配列型とJSON型

ご利用は計画的に

Page 147: PostgreSQLアンチパターン

困ったときの配列型とJSON型

ご利用は計画的に ↓

基本的に正規化しましょう

Page 148: PostgreSQLアンチパターン

あじぇんだ

1 自己紹介 2 とりあえず削除フラグ 3 困ったときの配列型とJSON型 4 マテビューの功罪 5 まとめ

Page 149: PostgreSQLアンチパターン

マテビューの功罪

マテビューはPostgreSQL 9.3から

Page 150: PostgreSQLアンチパターン

マテビューの功罪

•複雑なテーブルをシンプルに •遅いクエリを高速に •INDEXチューニングも可能

メリット

Page 151: PostgreSQLアンチパターン

マテビューの功罪

•表領域を使う •リフレッシュが必要 •リフレッシュのコストが高い

デメリット

Page 152: PostgreSQLアンチパターン

マテビューの功罪

•表領域を使う •リフレッシュが必要 •リフレッシュのコストが高い

デメリット

Page 153: PostgreSQLアンチパターン

マテビューの功罪

•表領域を使う •リフレッシュが必要 •リフレッシュのコストが高い

デメリット実体を持つのでデータファイルが作成される 作った分だけディスクスペースを圧迫する

Page 154: PostgreSQLアンチパターン

マテビューの功罪

•表領域を使う •リフレッシュが必要 •リフレッシュのコストが高い

デメリット実体を持つのでデータファイルが作成される 作った分だけディスクスペースを圧迫する

参照元のテーブルの増加と合わせてマテビューが増えれば指数的にディスクスペースの使用量が増える

Page 155: PostgreSQLアンチパターン

マテビューの功罪

•表領域を使う •リフレッシュが必要 •リフレッシュのコストが高い

デメリット

Page 156: PostgreSQLアンチパターン

マテビューの功罪

集計済み表課金log

計算結果をマテビューにする

Page 157: PostgreSQLアンチパターン

マテビューの功罪

集計済み表課金log

課金1

計算結果をマテビューにする

課金2

Page 158: PostgreSQLアンチパターン

マテビューの功罪

集計済み表課金log

課金1

計算結果をマテビューにする

課金2

リフレッシュ

Page 159: PostgreSQLアンチパターン

マテビューの功罪

集計済み表課金log

課金1 集計結果

計算結果をマテビューにする

課金2

リフレッシュ

Page 160: PostgreSQLアンチパターン

マテビューの功罪

集計済み表課金log

課金1 集計結果

計算結果をマテビューにする

課金2

集計結果を参照するので高速でシンプル!!

Page 161: PostgreSQLアンチパターン

マテビューの功罪

集計済み表課金log

課金1 集計結果

計算結果をマテビューにする

課金2

課金3

Page 162: PostgreSQLアンチパターン

マテビューの功罪

集計済み表課金log

課金1 集計結果

計算結果をマテビューにする

課金2

課金3

☓更新失敗

Page 163: PostgreSQLアンチパターン

マテビューの功罪

集計済み表課金log

課金1 集計結果

計算結果をマテビューにする

課金2

課金3

☓更新失敗

前回の更新結果のままなので不整合

Page 164: PostgreSQLアンチパターン

マテビューの功罪

更新が失敗した際の処理が必要

Page 165: PostgreSQLアンチパターン

マテビューの功罪

更新が失敗した際の処理が必要 ↓

自動更新の場合に アプリケーションで制御出来ない

Page 166: PostgreSQLアンチパターン

マテビューの功罪

更新が失敗した際の処理が必要 ↓

自動更新の場合に アプリケーションで制御出来ない

DBはテストの自動化も大変 未然にバグを検知しにくい

Page 167: PostgreSQLアンチパターン

マテビューの功罪

•表領域を使う •リフレッシュが必要 •リフレッシュのコストが高い

デメリット

Page 168: PostgreSQLアンチパターン

マテビューの功罪

•表領域を使う •リフレッシュが必要 •リフレッシュのコストが高い

デメリット

PostgreSQLには差分更新は無い →データがクエリの実行速度が遅ければ更新も遅い

Page 169: PostgreSQLアンチパターン

マテビューの功罪

•表領域を使う •リフレッシュが必要 •リフレッシュのコストが高い

デメリット

PostgreSQLには差分更新は無い →データがクエリの実行速度が遅ければ更新も遅い

データが大きくなるにつれ、負荷も上がる →特に集約関数を使ったようなクエリは

メモリに乗らなくなった瞬間に急激に遅くなる

Page 170: PostgreSQLアンチパターン

マテビューの功罪

•表領域を使う •リフレッシュが必要 •リフレッシュのコストが高い

デメリット

PostgreSQLには差分更新は無い →データがクエリの実行速度が遅ければ更新も遅い

データが大きくなるにつれ、負荷も上がる →特に集約関数を使ったようなクエリは

メモリに乗らなくなった瞬間に急激に遅くなる

更新が遅くなった事に気づきにくい

Page 171: PostgreSQLアンチパターン

マテビューの功罪

処方箋

Page 172: PostgreSQLアンチパターン

マテビューの功罪

DB状態を監視する

Page 173: PostgreSQLアンチパターン

マテビューの功罪

DB状態を監視する ↓

死活監視だけでは無く レコードの増加量やCPU使用率など

Page 174: PostgreSQLアンチパターン

マテビューの功罪

DB状態を監視する ↓

死活監視だけでは無く レコードの増加量やCPU使用率など

Zabbixを使っているならpg_monzなどを使う

Page 175: PostgreSQLアンチパターン

マテビューの功罪

兎にも角にもマテビューはしない

Page 176: PostgreSQLアンチパターン

マテビューの功罪

兎にも角にもマテビューはしない ↓

マテビューを集計してマテビュー のような闇を作らない

Page 177: PostgreSQLアンチパターン

マテビューの功罪

マテビューは便利だが銀の弾丸ではない ↓

必要になった時、それは多くの場合 設計に問題を抱えている

Page 178: PostgreSQLアンチパターン

マテビューの功罪

マテビューは便利だが銀の弾丸ではない ↓

必要になった時、それは多くの場合 設計に問題を抱えている

Page 179: PostgreSQLアンチパターン

マテビューの功罪

マテビューは便利だが銀の弾丸ではない ↓

必要になった時、それは多くの場合 設計に問題を抱えている

根本的な解決策が必要なので マテビューが必要になった時は設計を見直す

Page 180: PostgreSQLアンチパターン

マテビューの功罪

使わないに越した事は無い

Page 181: PostgreSQLアンチパターン

マテビューの功罪

使わないに越した事は無い ↓

積極的に使うものではない

Page 182: PostgreSQLアンチパターン

マテビューの功罪

使わないに越した事は無い ↓

積極的に使うものではない

新機能は使いたくなるけども

Page 183: PostgreSQLアンチパターン

あじぇんだ

1 自己紹介 2 とりあえず削除フラグ 3 困ったときの配列型とJSON型 4 マテビューの功罪 5 まとめ

Page 184: PostgreSQLアンチパターン

まとめ

PostgreSQLは高機能

Page 185: PostgreSQLアンチパターン

まとめ

PostgreSQLは高機能 ↓

設計の不備を 機能でカバー出来てしまう

Page 186: PostgreSQLアンチパターン

まとめ

機能に依存し過ぎない

Page 187: PostgreSQLアンチパターン

まとめ

機能に依存し過ぎない ↓

シンプルな設計は全てに勝る

Page 188: PostgreSQLアンチパターン

まとめ

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

Page 189: PostgreSQLアンチパターン

まとめ

周囲の経験談から学ぶ

Page 190: PostgreSQLアンチパターン

まとめ

周囲の経験談から学ぶ ↓

積極的にコミュニティを利用する

Page 191: PostgreSQLアンチパターン

参考資料

・公式ドキュメント(日本語) https://www.postgresql.jp/document/9.4/html/postgres-fdw.html

・postgresql-jp Slack(チャットルーム) https://postgresql-hackers-jp.herokuapp.com/

Page 192: PostgreSQLアンチパターン

まとめ

データの寿命はコードよりも長い

Page 193: PostgreSQLアンチパターン

まとめ

一度作ったDBは消せない

Page 194: PostgreSQLアンチパターン

まとめ

一度作ったDBは消せない ↓

設計が大事

Page 195: PostgreSQLアンチパターン

まとめ

より良い設計を

一緒に考えて行きましょう

Page 196: PostgreSQLアンチパターン

ご静聴ありがとうございました。