Upload
soudai-sone
View
2.704
Download
4
Embed Size (px)
Citation preview
知って得するWebで便利なPostgreSQLの3つの機能
オープンソースカンファレンス2015@新潟
What is it?
データベースは何を基準に選んでますか?
What is it?
RDBを制する者は
データ層を制する
と言っても過言ではありません
What is it?そして
PostgreSQLを使えば開発で楽をする
ことが出来ます
What is it?
今日はそんなPostgreSQLの
Tipsをご紹介します
あじぇんだ
1 自己紹介 2 Window関数とマテビュー 3 外部データラッパ(FDW) 4 JSON型とJSONB型 5 まとめ
あじぇんだ
1 自己紹介 2 Window関数とマテビュー 3 外部データラッパ(FDW) 4 JSON型とJSONB型 5 まとめ
自己紹介名前:曽根 壮大(そね たけとも) 年齢:30歳(三人の子供がいます) 職業:Webエンジニア
所属:日本PostgreSQLユーザ会
中国支部 支部長
技術的にはLL系言語とかRDBが好きです
MySQL使いが知るべき
PostgreSQLとの違いと変わらない一つのこと http://soudai1025.blogspot.jp/2015/08/mysql2postgresql.html
あじぇんだ
1 自己紹介 2 Window関数とマテビュー 3 外部データラッパ(FDW) 4 JSON型とJSONB型 5 まとめ
Window関数とマテビュー
Window関数とマテビュー
Window関数とマテビュー
素早く帳票を作る
Window関数とマテビュー
Window関数
Window関数とマテビュー
Window関数
ウィンドウ関数は現在の行に何らの関係するテーブル行の一纏まり全般の計算を行う。
商品名 売上 売上日プログラマのためのSQL 4200 2015-08-01"内部構造から学ぶ 3600 2015-08-30ソフトウェアデザイン 1300 2015-08-02SQL実践入門 2580 2015-08-03
理論から学ぶデータベース 3110 2015-08-04SQL逆引き大全363の極意 2600 2015-08-30プログラマのためのSQL 4200 2015-08-30
SQL実践入門 2580 2015-08-30理論から学ぶデータベース 3110 2015-08-05
SQL実践入門 2580 2015-08-30リーダブルコード 2592 2015-08-30リーダブルコード 2592 2015-08-30
データベース・リファクタ 3000 2015-08-30達人に学ぶDB設計 2800 2015-08-30
: :
: :
: :
※実務では編は正規化するべき
Window関数とマテビュー
まずは日別に集計する
実際のSQL
SELECT to_char( sum(“売上"),'FM999,999,999'
) AS "日別売上"
, "売上日"
FROM "売上表"
GROUP BY “売上日" ORDER BY "売上日"
実際のSQL
SELECT to_char( sum(“売上"),'FM999,999,999'
) AS "日別売上"
, "売上日"
FROM "売上表"
GROUP BY “売上日" ORDER BY "売上日"
実際のSQL
SELECT to_char( sum(“売上"),'FM999,999,999'
) AS "日別売上"
, "売上日"
FROM "売上表"
GROUP BY “売上日" ORDER BY "売上日"
3桁区切りでカンマを入れる
日別売上 売上日2,643,552 2015-08-012,650,368 2015-08-022,601,180 2015-08-032,598,392 2015-08-042,635,064 2015-08-052,650,852 2015-08-062,642,568 2015-08-072,613,876 2015-08-082,658,504 2015-08-092,637,376 2015-08-102,617,840 2015-08-112,596,896 2015-08-122,669,644 2015-08-132,623,568 2015-08-14
: :
: :
Window関数とマテビュー
前日との差分を出したい
Window関数とマテビュー
前日との差分を出したい ↓
lag()を使って集計する
実際のSQL
SELECT
*
, lag("日別売上") OVER (ORDER BY "売上日")AS 前日売上
FROM
(SELECT
to_char(sum("売上"),'FM999,999,999') AS "日別売上"
, "売上日"
FROM "売上表"
GROUP BY "売上日") AS "集計"
実際のSQL
SELECT
*
, lag("日別売上") OVER (ORDER BY "売上日")AS 前日売上
FROM
(SELECT
to_char(sum("売上"),'FM999,999,999') AS "日別売上"
, "売上日"
FROM "売上表"
GROUP BY "売上日") AS "集計"
実際のSQL
SELECT
*
, lag("日別売上") OVER (ORDER BY "売上日")AS 前日売上
FROM
(SELECT
to_char(sum("売上"),'FM999,999,999') AS "日別売上"
, "売上日"
FROM "売上表"
GROUP BY "売上日") AS "集計"
先ほどのクエリをサブクエリにする
実際のSQL
SELECT
*
, lag("日別売上") OVER (ORDER BY "売上日")AS 前日売上
FROM
(SELECT
to_char(sum("売上"),'FM999,999,999') AS "日別売上"
, "売上日"
FROM "売上表"
GROUP BY "売上日") AS "集計"
Window関数の対象を指定
先ほどのクエリをサブクエリにする
実際のSQL
SELECT
*
, lag("日別売上") OVER (ORDER BY "売上日")AS 前日売上
FROM
(SELECT
to_char(sum("売上"),'FM999,999,999') AS "日別売上"
, "売上日"
FROM "売上表"
GROUP BY "売上日") AS "集計"
Window関数の対象を指定
先ほどのクエリをサブクエリにする
前行の取得するカラムを指定
日別売上 売上日 前日売上2,643,552 2015-08-01 NULL2,650,368 2015-08-02 2,643,5522,601,180 2015-08-03 2,650,3682,598,392 2015-08-04 2,601,1802,635,064 2015-08-05 2,598,3922,650,852 2015-08-06 2,635,0642,642,568 2015-08-07 2,650,8522,613,876 2015-08-08 2,642,5682,658,504 2015-08-09 2,613,8762,637,376 2015-08-10 2,658,5042,617,840 2015-08-11 2,637,3762,596,896 2015-08-12 2,617,8402,669,644 2015-08-13 2,596,8962,623,568 2015-08-14 2,669,644
: :
: :
: :
日別売上 売上日 前日売上2,643,552 2015-08-01 NULL2,650,368 2015-08-02 2,643,5522,601,180 2015-08-03 2,650,3682,598,392 2015-08-04 2,601,1802,635,064 2015-08-05 2,598,3922,650,852 2015-08-06 2,635,0642,642,568 2015-08-07 2,650,8522,613,876 2015-08-08 2,642,5682,658,504 2015-08-09 2,613,8762,637,376 2015-08-10 2,658,5042,617,840 2015-08-11 2,637,3762,596,896 2015-08-12 2,617,8402,669,644 2015-08-13 2,596,8962,623,568 2015-08-14 2,669,644
: :
: :
: :
前行が無いのでNULL
Window関数とマテビュー
翌日の場合は?
Window関数とマテビュー
翌日の場合は? ↓
lead()を使って集計出来る
関数 説明row_number() 行番号
rank() ランキング (同率で番号を飛ばす)
dense_rank() ランキング (同率で番号を飛ばさない)
percent_rank() ランキング (%で表示) : (rank - 1) / (全行数 - 1)
cume_dist() percent_rank に類似 : (現在の行の位置) / (全行数)
ntile(N) ランキング (1..N に分割)
lag(value, offset, default) ソート状態での前の行の値
lead(value, offset, default) ソート状態での後の行の値
first_value(value) 最初の値
last_value(value) 最後の値
nth_value(value, N) N番目の値 (1から数える)
Window関数とマテビュー
データが多くて遅い
Window関数とマテビュー
マテリアライズドビュー
Window関数とマテビュー
マテリアライズドビュー
実体の存在するView。 参照したクエリ結果を保存するため、参照元を更新した際はマテビューの更新も必要になる。
※ただしPostgreSQL 9.3からの機能
Window関数とマテビュー
クエリ結果を実体化する
Window関数とマテビュー
クエリ結果を実体化する ↓ 高速化
Window関数とマテビュー
マテビューは銀の弾丸ではない
Window関数とマテビュー
マテビューの問題点
・リフレッシュ管理が必要(自動更新しない) ※ただし、9.4から自動更新が可能 ・普通のテーブル同様に表領域を消費する ・リフレッシュはそれなりにリソースを使う
Window関数とマテビュー
更新が多いとボトルネックになる
Window関数とマテビュー
まとめ
Window関数とマテビュー
まとめ
Window関数とマテビュー
まとめ
1 機能を覚えると実装が楽に
Window関数とマテビュー
まとめ
1 機能を覚えると実装が楽に 2 拡張を見据えた設計が大事
Window関数とマテビュー
まとめ
1 機能を覚えると実装が楽に 2 拡張を見据えた設計が大事 3 要件に合わせて選択肢を選ぶ
あじぇんだ
1 自己紹介 2 Window関数とマテビュー 3 外部データラッパ(FDW) 4 JSON型とJSONB型 5 まとめ
外部データラッパ(FDW)
Window関数が便利!!
外部データラッパ(FDW)
Window関数が便利!! ↓
でも弊社、MySQL(́・ω・`)
外部データラッパ(FDW)
でも大丈夫!!
外部データラッパ(FDW)
FDWを使えばMySQLと繋がる
FDWとは
外部テーブルを作成するための機能 (外部のデータをtableにする)
FDWとは
外部データにテーブルと同様に SQL文でアクセスできる
FDWとは
• WHEREやORDER BYが使える • GROUP BYなどの集合関数も使える • JOINなど、他tableと関連付け出来る • 更新や削除も出来る(ただし9.3から)
FDWとは
外部データ ↓
DB、CSV、JSON、WebAPIなんでも良い
FDWとは
PostgreSQL to
PostgreSQL
FDWとは
MySQL to
PostgreSQL
FDWとは
MongoDB to
PostgreSQL
FDWとは
Git to
PostgreSQL
SQL Databases Wrappers • postgres_fdw • oracle_fdw • mysql_fdw • odbc_fdw • jdbc_fdw
NoSQL Databases Wrappers• couchdb_fdw • MonetDB FDW • mongo_fdw • redis_fdw • Neo4j fdw • Tycoon FDW
Others• git_fdw • ldap_fdw • IMAP_fdw • s3_fdw • www_fdw • OS_fdw
FDWとは
その他に既に多くの実装がある
SQL Databases Wrappers • postgres_fdw • oracle_fdw • mysql_fdw • odbc_fdw • jdbc_fdw
FDWを使うMySQLPostgreSQL
FDWを使うMySQLPostgreSQL
TABLE
FDWを使う
EXTENSION
MySQLPostgreSQL
TABLE
FDWを使う
EXTENSION
MySQLPostgreSQL
TABLE
mysql_fdwをインストールする
FDWを使う
server
EXTENSION
USER MAPPING
MySQLPostgreSQL
TABLE
FDWを使う
server
EXTENSION
USER MAPPING
MySQLPostgreSQL
TABLE
MySQLの接続先を設定する
MySQLの接続ユーザを設定する
FDWを使う
server
FOREIGN TABLE
EXTENSION
USER MAPPING
MySQLPostgreSQL
TABLE
FDWを使う
server
FOREIGN TABLE
EXTENSION
USER MAPPING
MySQLPostgreSQL
TABLE
PostgreSQLの外部tableを作成する
FDWを使う
server
FOREIGN TABLE
EXTENSION
USER MAPPING
MySQLPostgreSQL
TABLE
Client
FDWを使う
server
FOREIGN TABLE
EXTENSION
USER MAPPING
MySQLPostgreSQL
TABLE
ClientSQLで問い合わせ
FDWを使う
server
FOREIGN TABLE
EXTENSION
USER MAPPING
MySQLPostgreSQL
TABLE
ClientSQLで問い合わせ
外部tableにアクセス
FDWを使う
server
FOREIGN TABLE
EXTENSION
USER MAPPING
MySQLPostgreSQL
TABLE
Client
アクセス先を確認
FDWを使う
server
FOREIGN TABLE
EXTENSION
USER MAPPING
MySQLPostgreSQL
TABLE
Client
MySQLにクエリを投げる
FDWを使う
server
FOREIGN TABLE
EXTENSION
USER MAPPING
MySQLPostgreSQL
TABLE
Client
実行結果を取得
FDWを使う
server
FOREIGN TABLE
EXTENSION
USER MAPPING
MySQLPostgreSQL
TABLE
Client実行結果を表示
FDWを使う
server
FOREIGN TABLE
EXTENSION
USER MAPPING
MySQLPostgreSQL
TABLE
Client
FDWを使う
既存環境の集計作業が大変 ↓
そのままPostgreSQLに委託出来る
あじぇんだ
1 自己紹介 2 Window関数とマテビュー 3 外部データラッパ(FDW) 4 JSON型とJSONB型 5 まとめ
JSON型とJSONB型
PostgreSQLで今一番アツい機能
※そーだい調べ
JSON型とJSONB型
ドキュメント指向
JSON型とJSONB型
ドキュメント指向
“name” : “hoge” “role1” : 開発 “role2” : 運用 “age” : 30
“name” : “fuga” “role1” : 営業 “from” : 広島 “age” : 25
“name” : “bar” “role1” : 総務
JSON型とJSONB型
ドキュメント指向
“name” : “hoge” “role1” : 開発 “role2” : 運用 “age” : 30
“name” : “fuga” “role1” : 営業 “from” : 広島 “age” : 25
“name” : “bar” “role1” : 総務
それぞれが独立したドキュメント ドキュメントにはユニークなIDでアクセスが可能
JSON型とJSONB型
ドキュメント指向
“name” : “hoge” “role1” : 開発 “role2” : 運用 “age” : 30
“name” : “fuga” “role1” : 営業 “from” : 広島 “age” : 25
“name” : “bar” “role1” : 総務
それぞれが独立しているので 自由な変更が可能
id name properties
1 test1 {“name”:”hoge",“age”:30,”role”:1}
2 test2 {“name”:”fuga",“age”:21,”role”:1}
3 test3 {“name”:”bar”,“age”:22,”role”:1}
4 test4 {“name”:”foo”,“age”:60,”role”:2}
5 test5 {“name”:toto,“age”:16,”role”:2}
6 test6 {“name”:”titi”,“age”:30,”role”:2}
7 test7 {“name”:”tata”,“age”:30,”role”:3}
: :
: :
: :
JSON型とJSONB型
値を指定した検索
実際のSQL
SELECT
*
FROM
demo_json
WHERE
properties->>”name” = “hoge”
実際のSQL
SELECT
*
FROM
demo_json
WHERE
properties->>”name” = “hoge”JSONの値を指定して直接検索出来る
JSON型とJSONB型
INDEXを指定する
実際のSQL
CREATE INDEX
demo_json_index
ON
demo_json
(properties->>'name');
実際のSQL
CREATE INDEX
demo_json_index
ON
demo_json
(properties->>'name');
INDEX名
実際のSQL
CREATE INDEX
demo_json_index
ON
demo_json
(properties->>'name');
INDEX名
対象テーブル
実際のSQL
CREATE INDEX
demo_json_index
ON
demo_json
(properties->>'name');
INDEX名
対象テーブル
式を指定する
JSON型とJSONB型
銀の弾丸ではない(本日二度目
JSON型とJSONB型
制約を設けれない
JSON型とJSONB型
制約を設けれない ↓
外部キーや一意制約がない
JSON型とJSONB型
データ登録のトレードオフ
JSON型とJSONB型
データ登録のトレードオフ ↓
自由な保存 ⇔ 正しく守る
JSON型とJSONB型
クエリに対する制限
JSON型とJSONB型
クエリに対する制限 ↓
集約関数などが使えない
JSON型とJSONB型
要件に合わせて選択肢を選ぶ
JSON型とJSONB型
まとめ
1 値で検索が出来る 2 値の検索でINDEXが使える 3 要件に合わせて選択肢を選ぶ
あじぇんだ
1 自己紹介 2 Window関数とマテビュー 3 外部データラッパ(FDW) 4 JSON型とJSONB型 5 まとめ
まとめ
Webアプリケーションの複雑化
まとめ
Webアプリケーションの複雑化 ↓
データ構造も複雑化
まとめ
柔軟で高速な検索が必要
まとめ
柔軟で高速な検索が必要 ↓
運用では正しいデータの保存も重要
まとめ
データベースを知ることが大事
まとめ
PostgreSQLは
Webにもマッチします
まとめ
スタートアップに
まとめ
リプレースに
まとめ
既存拡張に
まとめ
PostgreSQL使ってみませんか?
ご静聴ありがとうございました。