SlideShare une entreprise Scribd logo
1  sur  21
Télécharger pour lire hors ligne
第6回 PostgreSQLアンカンファレンス 1/21
第6回 PostgreSQLアンカンファレンス
[9.5新機能]
追加されたGROUP BY機能の使い方
Kosuke Kida
SlideShareへの公開にあたり、2015年12月12日(土)アンカンファレンス当日の発表後に
いただいたコメントを元に一部項目を追加しています。
主な追記箇所
 P.9  分析系の用途でDB選択時、本機能追加がどう影響するかコメント
 P.10- CUBEの実行計画をより分かりやすいものに変更、スライド追加
 P.20- 最後に挙げた疑問点のうち、解決の糸口になりそうな情報を発表後の質疑から追記
※追記個所は本テキストボックスと同色の枠で記載
第6回 PostgreSQLアンカンファレンス 2/21
アジェンダ
9.5の新機能を勉強中のうちの一つを発表してみる
● 標準SQLへの対応
● 良いところ
● 実用シーンを考察
● マニュアルにないところの疑問
仕事ではPostgreSQL、Postgres Plusのプリセールス、他DBからの移行評価、環境構築、
トラブル対応などやっています。(PostgreSQLを知らない)顧客対応がほとんどの中で、
どんな情報が有益か考える中で、ベータ版時点から自分で触って、使い方、使いどころを
掴もうと試みています。(Ver9.3ぐらいから)
 ・特にアンカンファレンスが開催されるようになって、新機能に対する
  初めの一歩のハードルが大きく下がった
 ・どういうシーンで使えるかまで考えておくと、お客様からの反応が大きい
 ・分析系の用途でPostgreSQLはどこまで使えるか、という相談は最近多いので
  BRINインデックスとか、集計構文とか、結構注目されてる
第6回 PostgreSQLアンカンファレンス 3/21
標準SQLへの対応
1クエリで複数の集計を組合せて取得
● GROUP BY GROUPING SETS
✔ こんな売上実績データ(result表、item表、shop表をJOIN)
SELECT r_date::date date,s_name,i_name,r_qt,r_qt * i_price sales
FROM result
JOIN item ON r_item = i_code
JOIN shop ON i_shop = s_id
ORDER BY r_date;
r_date | s_name | i_name | r_qt | sales
------------+------------+--------------+------+--------
2015-10-30 | Paul Smith | スラックス | 1 | 20000
2015-10-30 | Dior | シャツ | 2 | 60000
2015-10-30 | Dior | 冬ジャケット | 1 | 100000
2015-10-30 | Paul Smith | シャツ | 1 | 15000
2015-10-31 | DIESEL | ダメージB | 1 | 35000
2015-10-31 | DIESEL | ストレート | 2 | 50000
2015-10-31 | Dior | 冬ジャケット | 1 | 100000
2015-10-31 | Dior | シャツ | 1 | 30000
2015-11-01 | Paul Smith | シャツ | 3 | 45000
2015-11-02 | DIESEL | ダメージA | 1 | 30000
第6回 PostgreSQLアンカンファレンス 4/21
標準SQLへの対応
1クエリで複数の集計を組合せて取得
● GROUP BY GROUPING SETS
✔ 日別の売上集計と店舗毎の売り上げ集計が欲しい
SELECT r_date::date date
     ,sum(r_qt * i_price) sum
FROM result
JOIN item ON r_item = i_code
JOIN shop ON i_shop = s_id
GROUP BY date ORDER BY sum DESC;
date | sum
------------+--------
2015-10-31 | 215000
2015-10-30 | 195000
2015-11-08 | 50000
2015-11-01 | 45000
2015-11-03 | 45000
2015-11-02 | 45000
2015-11-07 | 40000
2015-11-06 | 30000
 :
SELECT s_name shop
     ,sum(r_qt * i_price) sum
FROM result
JOIN item ON r_item = i_code
JOIN shop ON i_shop = s_id
GROUP BY shop ORDER BY sum DESC;
shop | sum
------------+--------
Dior | 350000
DIESEL | 195000
Paul Smith | 165000
(3 行)
第6回 PostgreSQLアンカンファレンス 5/21
標準SQLへの対応
1クエリで複数の集計を組合せて取得
● GROUP BY GROUPING SETS
✔ 1クエリで店舗別、日別、総計を取得
SELECT s_name shop,r_date::date date,sum(r_qt * i_price) sum
FROM result
JOIN item ON r_item = i_code
JOIN shop ON i_shop = s_id
GROUP BY GROUPING SETS ((shop),(date),());
shop | date | sum
------------+------------+--------
DIESEL | | 195000
Dior | | 350000
Paul Smith | | 165000
| | 710000 /*総計*/
| 2015-10-30 | 195000
| 2015-10-31 | 215000
| 2015-11-01 | 45000
| 2015-11-02 | 45000
| 2015-11-03 | 45000
             :
第6回 PostgreSQLアンカンファレンス 6/21
標準SQLへの対応
1クエリで複数の集計を組合せて取得
● ROLLUP
✔ 1クエリで店舗-日付の組合せ、店舗別売上、総計を取得
SELECT s_name shop,r_date::date date
     ,sum(r_qt * i_price) sum
FROM result
JOIN item ON r_item = i_code
JOIN shop ON i_shop = s_id
GROUP BY ROLLUP ((shop),(date));
shop | date | sum
------------+------------+--------
DIESEL | 2015-10-31 | 85000
DIESEL | 2015-11-02 | 30000
DIESEL | 2015-11-06 | 30000
DIESEL | | 195000
Dior | 2015-10-30 | 160000
Dior | 2015-10-31 | 130000
Dior | | 350000
Paul Smith | 2015-10-30 | 35000
Paul Smith | 2015-11-01 | 45000
Paul Smith | 2015-11-02 | 15000
Paul Smith | | 165000
| | 710000
(結果はスライド用にところどころ省略)
第6回 PostgreSQLアンカンファレンス 7/21
標準SQLへの対応
1クエリで複数の集計を組合せて取得
● CUBE
✔ 1クエリで店舗-日付の組合せ、店舗別売上、日別売上、総計を取得
SELECT s_name shop,r_date::date date
     ,sum(r_qt * i_price) sum
FROM result
JOIN item ON r_item = i_code
JOIN shop ON i_shop = s_id
GROUP BY CUBE ((shop),(date));
shop | date | sum
------------+------------+--------
DIESEL | 2015-10-31 | 85000
DIESEL | 2015-11-02 | 30000
DIESEL | | 195000
Dior | 2015-10-30 | 160000
Dior | 2015-11-08 | 30000
Dior | | 350000
Paul Smith | 2015-10-30 | 35000
Paul Smith | 2015-11-01 | 45000
Paul Smith | 2015-11-02 | 15000
Paul Smith | 2015-11-08 | 20000
Paul Smith | | 165000
| | 710000
| 2015-10-30 | 195000
| 2015-10-31 | 215000
| 2015-11-08 | 50000
(結果はスライド用にところどころ省略)
第6回 PostgreSQLアンカンファレンス 8/21
良いところ(教科書的な)
1クエリで結果を取得できるので
● APとDBのやりとりの回数を削減
日別集計
店舗別集計
総計
あらゆる組合せ
第6回 PostgreSQLアンカンファレンス 9/21
良いところ(教科書的な)
1クエリで結果を取得できるので
● SeqScanの回数を削減
日別集計 30分
店舗別集計 30分
総計 30分
あらゆる組合せ 1時間
分析用途で現状PostgreSQLが
どの程度使えるのか?
という問いに対して、回答は、
今のところ、リアルタイム性を
どこまで求めるかだと思う。
---
左記に近い実際にあった例だと、
1日1回、オンライン系のシステム
から実績データを取込み、夜間
バッチで加工・集計して、複数の
Mビューで保持しとく使い方。
夜間のうちに完了するかどうかが
DB選定の肝になっていた。
構文が追加された事による
実行計画の効率化が採用可否の
分岐点になりそうな予感。
---
※ちなみにOracle EEで限界まで
チューニングして同じことをやると
1秒で結果が得られるとか、
それぐらいのスピード感になりそうな話。
「こ、これがリアルタイムか・・・ぐぬぬ」
第6回 PostgreSQLアンカンファレンス 10/21
実用シーンを考察
実行計画はどうなるか
● CUBEの実行計画を確認する
 
 
 
 
 
 
 
✔ このテーブルに対して従来の各項目別にGROUP BYすると
– 全件のカウント 306.755 ms
– アイテム種別カウント 718.326 ms
– 売上日別カウント 596.246 ms
– 売上店舗別カウント 609.198 ms  計2200 msぐらい
✔ CUBEでは加えて「日別-アイテム別」や「日別-店舗別」等、全組合せ集計結果を取得
-- CUBEのみの実行計画を見たい。
-- JOINの影響をなくすため、類似のデータを単一のテーブルで用意
-- 100万件超えるまで、適当にINSERT INTO huge SELECT * FROM result JOIN item・・・
postgres=# SELECT count(*) FROM huge;
count
---------
1310720
postgres=# show work_mem;
work_mem
----------
4MB   -- デフォルト
第6回 PostgreSQLアンカンファレンス 11/21
実用シーンを考察
実行計画はどうなるか
● SeqScanの回数を削減
✔ ただし、ソートが激増してDISKソートになると劇遅(2.2秒→7.8秒)
postgres=# EXPLAIN ANALYZE
postgres-# SELECT sales_date::date,shop,kind,count(*) FROM huge
postgres-# GROUP BY CUBE ((sales_date::date),(shop),(kind));
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------
GroupAggregate (cost=194723.79..566418.36 rows=336 width=26) (actual time=2671.543..7775.091 rows=69 loops=1)
Group Key: ((sales_date)::date), shop, kind
Group Key: ((sales_date)::date), shop
Group Key: ((sales_date)::date)
Group Key: ()
Sort Key: kind, ((sales_date)::date)
Group Key: kind, ((sales_date)::date)
Group Key: kind
Sort Key: shop, kind
Group Key: shop, kind
Group Key: shop
-> Sort (cost=194723.79..198000.59 rows=1310720 width=26) (actual time=2501.926..3181.656 rows=1310720 loops=1)
Sort Key: ((sales_date)::date), shop, kind
Sort Method: external merge Disk: 42216kB
-> Seq Scan on huge (cost=0.00..30182.00 rows=1310720 width=26)
(actual time=0.023..290.534 rows=1310720 loops=1)
Planning time: 0.141 ms
Execution time: 7788.108 ms
(17 行)
第6回 PostgreSQLアンカンファレンス 12/21
実用シーンを考察
実行計画はどうなるか
● SeqScanの回数を削減
✔ ただし、ソートが激増してDISKソートになると劇遅
✔ work_memの増加で対処(2.2秒→7.8秒→3.0秒)
postgres=# set work_mem to '200MB';
SET
postgres=# EXPLAIN ANALYZE
SELECT sales_date::date,shop,kind,count(*) FROM huge
GROUP BY CUBE ((sales_date::date),(shop),(kind));
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------
GroupAggregate (cost=163363.79..472338.36 rows=336 width=26) (actual time=1041.637..2986.535 rows=69 loops=1)
Group Key: ((sales_date)::date), shop, kind
Group Key: ((sales_date)::date), shop
Group Key: ((sales_date)::date)
Group Key: ()
Sort Key: kind, ((sales_date)::date)
Group Key: kind, ((sales_date)::date)
Group Key: kind
Sort Key: shop, kind
Group Key: shop, kind
Group Key: shop
-> Sort (cost=163363.79..166640.59 rows=1310720 width=26) (actual time=978.680..1147.774 rows=1310720 loops=1)
Sort Key: ((sales_date)::date), shop, kind
Sort Method: quicksort Memory: 149662kB
-> Seq Scan on huge (cost=0.00..30182.00 rows=1310720 width=26)
(actual time=0.030..316.498 rows=1310720 loops=1)
Planning time: 0.238 ms
Execution time: 3006.193 ms
(17 行)
第6回 PostgreSQLアンカンファレンス 13/21
実用シーンを考察
実行計画はどうなるか
● CUBEの実行計画を確認する
✔ このテーブルに対して従来の各項目別にGROUP BYすると
– 全件のカウント 306.755 ms
– アイテム種別カウント 718.326 ms
– 売上日別カウント 596.246 ms
– 売上店舗別カウント 609.198 ms  計2200 msぐらい
✔ CUBEでは加えて「日別-アイテム別」や「日別-店舗別」等、全組合せ集計結果を取得
– 全件のカウント
– アイテム種別カウント
– 売上日別カウント
– 売上店舗別カウント
– 日別-アイテム別カウント
– 日別-店舗別カウント
– アイテム別ー店舗別カウント
– 日別ーアイテム別ー店舗別カウント   計3000 ms ぐらい
第6回 PostgreSQLアンカンファレンス 14/21
実用シーンを考察
クロス集計までDBで行う
● クロス集計
✔ 何かのアイテムに関する街頭調査結果みたいなイメージ
✔ それぞれの枠に対してクエリを書いてデータを取得する必要があった
✔ CUBEならこれを1クエリで取得できているので、
あとは「行列変換して表示」できればOKなのだが。
性別 男 女 合計
年代 ~20代 それ以上 ~20代 それ以上 --
アイテムA 10人 10人 80人 100人 200人
アイテムB 20人 10人 50人 80人 160人
アイテムC 30人 10人 50人 50人 140人
合計 60人 30人 180人 230人 500人
第6回 PostgreSQLアンカンファレンス 15/21
実用シーンを考察
1クエリで複数の集計を組合せて取得
● CUBEでは、クロス集計表を埋める結果はすべて取得済み
✔ 1クエリで店舗-日付の組合せ、店舗別売上、日別売上、総計を取得
SELECT s_name shop,r_date::date date
     ,sum(r_qt * i_price) sum
FROM result
JOIN item ON r_item = i_code
JOIN shop ON i_shop = s_id
GROUP BY CUBE ((shop),(date));
shop | date | sum
------------+------------+--------
DIESEL | 2015-10-31 | 85000
DIESEL | 2015-11-02 | 30000
DIESEL | | 195000
Dior | 2015-10-30 | 160000
Dior | 2015-11-08 | 30000
Dior | | 350000
Paul Smith | 2015-10-30 | 35000
Paul Smith | 2015-11-01 | 45000
Paul Smith | 2015-11-02 | 15000
Paul Smith | 2015-11-08 | 20000
Paul Smith | | 165000
| | 710000
| 2015-10-30 | 195000
| 2015-10-31 | 215000
| 2015-11-08 | 50000
(結果はスライド用にところどころ省略)
shop | date | sum
------------+------------+--------
DIESEL | 2015-10-31 | 85000
DIESEL | 2015-11-02 | 30000
DIESEL | | 195000
Dior | 2015-10-30 | 160000
Dior | 2015-11-08 | 30000
Dior | | 350000
Paul Smith | 2015-10-30 | 35000
Paul Smith | 2015-11-01 | 45000
Paul Smith | 2015-11-02 | 15000
Paul Smith | 2015-11-08 | 20000
Paul Smith | | 165000
| | 710000
| 2015-10-30 | 195000
| 2015-10-31 | 215000
| 2015-11-08 | 50000
(結果はスライド用にところどころ省略)
第6回 PostgreSQLアンカンファレンス 16/21
実用シーンを考察
クロス集計までDBで完結する
● クロス集計
✔ tablefuncエクステンションでクロス集計
# rpm -ivh postgresql95-contrib-9.5-beta1_1PGDG.el6.x86_64.rpm
# psql
postgres=# create extension tablefunc;
CREATE EXTENSION
第6回 PostgreSQLアンカンファレンス 17/21
実用シーンを考察
クロス集計までDBで完結する
● クロス集計
✔ tablefuncエクステンションでクロス集計
--CUBE結果をMViewに保存(tablefuncの構文をシンプルにしたいので今回はコレで。)
CREATE MATERIALIZED VIEW mv_cube AS
SELECT sales_date::date,shop,kind,count(*) FROM result
GROUP BY CUBE ((sales_date::date),(shop),(kind));
--crosstab関数をかませて結果を整形
SELECT * FROM crosstab('
SELECT date,COALESCE(shop,''null''),sum FROM mv_cube     --整形したいクエリ
ORDER BY date
','
SELECT DISTINCT COALESCE(shop,''null'') shop FROM mv_cube --2番目の引数は
ORDER BY shop NULLS LAST --結果の列名に対応
')
AS sales (
date date
,"DIESEL" numeric
,"Dior" numeric
,"Paul Smith" numeric
,"daily sum" numeric
);
第6回 PostgreSQLアンカンファレンス 18/21
date | DIESEL | Dior | Paul Smith | daily sum
------------+--------+--------+------------+-----------
2015-10-30 | | 160000 | 35000 | 195000
2015-10-31 | 85000 | 130000 | | 215000
2015-11-01 | | | 45000 | 45000
2015-11-02 | 30000 | | 15000 | 45000
2015-11-03 | 25000 | | 20000 | 45000
2015-11-04 | | 30000 | | 30000
2015-11-05 | | | 15000 | 15000
2015-11-06 | 30000 | | | 30000
2015-11-07 | 25000 | | 15000 | 40000
2015-11-08 | | 30000 | 20000 | 50000
| 195000 | 350000 | 165000 | 710000
(11 行)
実用シーンを考察
クロス集計までDBで完結する
● クロス集計
✔ tablefuncエクステンションでクロス集計
第6回 PostgreSQLアンカンファレンス 19/21
date | DIESEL | Dior | Paul Smith | daily sum
------------+--------+--------+------------+-----------
2015-10-30 | | 160000 | 35000 | 195000
2015-10-31 | 85000 | 130000 | | 215000
2015-11-01 | | | 45000 | 45000
2015-11-02 | 30000 | | 15000 | 45000
2015-11-03 | 25000 | | 20000 | 45000
2015-11-04 | | 30000 | | 30000
2015-11-05 | | | 15000 | 15000
2015-11-06 | 30000 | | | 30000
2015-11-07 | 25000 | | 15000 | 40000
2015-11-08 | | 30000 | 20000 | 50000
| 195000 | 350000 | 165000 | 710000
(11 行)
実用シーンを考察
クロス集計までDBで完結する
● クロス集計
✔ tablefuncエクステンションでクロス集計
date | DIESEL | Dior | Paul Smith | daily sum
------------+--------+--------+------------+-----------
2015-10-30 | | 160000 | 35000 | 195000
2015-10-31 | 85000 | 130000 | | 215000
2015-11-01 | | | 45000 | 45000
2015-11-02 | 30000 | | 15000 | 45000
2015-11-03 | 25000 | | 20000 | 45000
2015-11-04 | | 30000 | | 30000
2015-11-05 | | | 15000 | 15000
2015-11-06 | 30000 | | | 30000
2015-11-07 | 25000 | | 15000 | 40000
2015-11-08 | | 30000 | 20000 | 50000
| 195000 | 350000 | 165000 | 710000
(11 行)
第6回 PostgreSQLアンカンファレンス 20/21
マニュアルで見つけられなかった疑問
grouping関数の存在と役割
● 標準SQLやOracleの構文を見ていると登場するGROUPING関数
✔ 指定してみたらPostgreSQL 9.5でも使えた
✔ しかしマニュアルに無く、pg_procなどからも定義が探せない
SELECT grouping(s_name) AS g1
,grouping(r_date::date) AS g2
,grouping(s_name,r_date::date) AS gX
,s_name shop,r_date::date date,sum(r_qt * i_price) sum
FROM result
JOIN item ON r_item = i_code
JOIN shop ON i_shop = s_id
GROUP BY GROUPING SETS ((shop),(date),());
g1 | g2 | gx | shop | date | sum
----+----+----+------------+------------+--------
0 | 1 | 1 | DIESEL | | 195000
0 | 1 | 1 | Dior | | 350000
0 | 1 | 1 | Paul Smith | | 165000
1 | 1 | 3 | | | 710000
1 | 0 | 2 | | 2015-10-30 | 195000
1 | 0 | 2 | | 2015-10-31 | 215000
この実行例が意味をあらわしている?
本当にnullだったか、グルーピングされた結果かどうか
gXの3は、2進数の11?項目が増えたら?
第6回 PostgreSQLアンカンファレンス 21/21
マニュアルで見つけられなかった疑問
grouping関数の存在と役割
● 標準SQLやOracleの構文を見ていると登場するGROUPING関数
✔ 指定してみたらPostgreSQL 9.5でも使えた
✔ しかしマニュアルに無く、pg_procなどからも定義が探せない
– パーサーのソースコード中にそれらしき定義がありそう
– http://doxygen.postgresql.org/で検索してみたら、確かにそんな感じ
groupingは関数ではなく、構造体?の扱い
パーサーのコードの中にありそう
詳細は後日確認します!

Contenu connexe

Tendances

my sql-postgresql勉強会#6 LT 私的なPostgreSQLの楽しみ方
my sql-postgresql勉強会#6 LT 私的なPostgreSQLの楽しみ方my sql-postgresql勉強会#6 LT 私的なPostgreSQLの楽しみ方
my sql-postgresql勉強会#6 LT 私的なPostgreSQLの楽しみ方
Toshi Harada
 

Tendances (20)

Chugoku db 20th-postgresql-10-pub
Chugoku db 20th-postgresql-10-pubChugoku db 20th-postgresql-10-pub
Chugoku db 20th-postgresql-10-pub
 
Chugokudb18_1
Chugokudb18_1Chugokudb18_1
Chugokudb18_1
 
KOF2015 PostgreSQL 9.5
KOF2015 PostgreSQL 9.5KOF2015 PostgreSQL 9.5
KOF2015 PostgreSQL 9.5
 
Pgunconf 20121212-postgeres fdw
Pgunconf 20121212-postgeres fdwPgunconf 20121212-postgeres fdw
Pgunconf 20121212-postgeres fdw
 
PostgreSQL 10 新機能 @オープンセミナー香川 2017
PostgreSQL 10 新機能 @オープンセミナー香川 2017PostgreSQL 10 新機能 @オープンセミナー香川 2017
PostgreSQL 10 新機能 @オープンセミナー香川 2017
 
Hackers Champloo 2016 postgresql-9.6
Hackers Champloo 2016 postgresql-9.6Hackers Champloo 2016 postgresql-9.6
Hackers Champloo 2016 postgresql-9.6
 
PostgreSQL10徹底解説
PostgreSQL10徹底解説PostgreSQL10徹底解説
PostgreSQL10徹底解説
 
PostgreSQL 10 新機能 @OSC 2017 Fukuoka
PostgreSQL 10 新機能 @OSC 2017 FukuokaPostgreSQL 10 新機能 @OSC 2017 Fukuoka
PostgreSQL 10 新機能 @OSC 2017 Fukuoka
 
pg_bigmを用いた全文検索のしくみ(前編)
pg_bigmを用いた全文検索のしくみ(前編)pg_bigmを用いた全文検索のしくみ(前編)
pg_bigmを用いた全文検索のしくみ(前編)
 
Chugokudb study-20150131
Chugokudb study-20150131Chugokudb study-20150131
Chugokudb study-20150131
 
my sql-postgresql勉強会#6 LT 私的なPostgreSQLの楽しみ方
my sql-postgresql勉強会#6 LT 私的なPostgreSQLの楽しみ方my sql-postgresql勉強会#6 LT 私的なPostgreSQLの楽しみ方
my sql-postgresql勉強会#6 LT 私的なPostgreSQLの楽しみ方
 
アナリティクスをPostgreSQLで始めるべき10の理由@第6回 関西DB勉強会
アナリティクスをPostgreSQLで始めるべき10の理由@第6回 関西DB勉強会アナリティクスをPostgreSQLで始めるべき10の理由@第6回 関西DB勉強会
アナリティクスをPostgreSQLで始めるべき10の理由@第6回 関西DB勉強会
 
PGCon.jp 2014 jsonb-datatype-20141205
PGCon.jp 2014 jsonb-datatype-20141205PGCon.jp 2014 jsonb-datatype-20141205
PGCon.jp 2014 jsonb-datatype-20141205
 
Postgre sql9.3新機能紹介
Postgre sql9.3新機能紹介Postgre sql9.3新機能紹介
Postgre sql9.3新機能紹介
 
Vacuum徹底解説
Vacuum徹底解説Vacuum徹底解説
Vacuum徹底解説
 
Webで役立つRDBの使い方
Webで役立つRDBの使い方Webで役立つRDBの使い方
Webで役立つRDBの使い方
 
pg_bigm(ピージー・バイグラム)を用いた全文検索のしくみ(後編)
pg_bigm(ピージー・バイグラム)を用いた全文検索のしくみ(後編)pg_bigm(ピージー・バイグラム)を用いた全文検索のしくみ(後編)
pg_bigm(ピージー・バイグラム)を用いた全文検索のしくみ(後編)
 
PostgreSQL9.3新機能紹介
PostgreSQL9.3新機能紹介PostgreSQL9.3新機能紹介
PostgreSQL9.3新機能紹介
 
GPUとSSDがPostgreSQLを加速する~クエリ処理スループット10GB/sへの挑戦~ [DB Tech Showcase Tokyo/2017]
GPUとSSDがPostgreSQLを加速する~クエリ処理スループット10GB/sへの挑戦~ [DB Tech Showcase Tokyo/2017]GPUとSSDがPostgreSQLを加速する~クエリ処理スループット10GB/sへの挑戦~ [DB Tech Showcase Tokyo/2017]
GPUとSSDがPostgreSQLを加速する~クエリ処理スループット10GB/sへの挑戦~ [DB Tech Showcase Tokyo/2017]
 
Jpug study-postgre sql-10-pub
Jpug study-postgre sql-10-pubJpug study-postgre sql-10-pub
Jpug study-postgre sql-10-pub
 

Similaire à [9.5新機能]追加されたgroupbyの使い方

Counter Table Pattern & Temporary Table Pattern (2012-04-13 CDP Night)
Counter Table Pattern & Temporary Table Pattern (2012-04-13 CDP Night)Counter Table Pattern & Temporary Table Pattern (2012-04-13 CDP Night)
Counter Table Pattern & Temporary Table Pattern (2012-04-13 CDP Night)
Ryuichi Tokugami
 
データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回
Naoyuki Yamada
 
SQLチューニング入門 入門編
SQLチューニング入門 入門編SQLチューニング入門 入門編
SQLチューニング入門 入門編
Miki Shimogai
 

Similaire à [9.5新機能]追加されたgroupbyの使い方 (20)

Apuri she ji_gaido_teburushe_ji__v1.0
Apuri she ji_gaido_teburushe_ji__v1.0Apuri she ji_gaido_teburushe_ji__v1.0
Apuri she ji_gaido_teburushe_ji__v1.0
 
Bind Peek をもっと使おうぜ!(柴田 歩) - JPOUG Advent Calendar 2014(Day 5) -
Bind Peek をもっと使おうぜ!(柴田 歩) - JPOUG Advent Calendar 2014(Day 5) -Bind Peek をもっと使おうぜ!(柴田 歩) - JPOUG Advent Calendar 2014(Day 5) -
Bind Peek をもっと使おうぜ!(柴田 歩) - JPOUG Advent Calendar 2014(Day 5) -
 
はじめてのAmazon Redshift
はじめてのAmazon RedshiftはじめてのAmazon Redshift
はじめてのAmazon Redshift
 
Counter Table Pattern & Temporary Table Pattern (2012-04-13 CDP Night)
Counter Table Pattern & Temporary Table Pattern (2012-04-13 CDP Night)Counter Table Pattern & Temporary Table Pattern (2012-04-13 CDP Night)
Counter Table Pattern & Temporary Table Pattern (2012-04-13 CDP Night)
 
[Cloud OnAir] 最新アップデート Google Cloud データ関連ソリューション 2020年5月14日 放送
[Cloud OnAir] 最新アップデート Google Cloud データ関連ソリューション 2020年5月14日 放送[Cloud OnAir] 最新アップデート Google Cloud データ関連ソリューション 2020年5月14日 放送
[Cloud OnAir] 最新アップデート Google Cloud データ関連ソリューション 2020年5月14日 放送
 
MySQL 5.7 トラブルシューティング 性能解析入門編
MySQL 5.7 トラブルシューティング 性能解析入門編MySQL 5.7 トラブルシューティング 性能解析入門編
MySQL 5.7 トラブルシューティング 性能解析入門編
 
これでBigQueryをドヤ顔で語れる!BigQueryの基本
これでBigQueryをドヤ顔で語れる!BigQueryの基本これでBigQueryをドヤ顔で語れる!BigQueryの基本
これでBigQueryをドヤ顔で語れる!BigQueryの基本
 
データベースシステム論12 - 問い合わせ処理と最適化
データベースシステム論12 - 問い合わせ処理と最適化データベースシステム論12 - 問い合わせ処理と最適化
データベースシステム論12 - 問い合わせ処理と最適化
 
V$SQLとその周辺でER図を描いてみよう!
V$SQLとその周辺でER図を描いてみよう!V$SQLとその周辺でER図を描いてみよう!
V$SQLとその周辺でER図を描いてみよう!
 
PostgreSQL14の pg_stat_statements 改善(第23回PostgreSQLアンカンファレンス@オンライン 発表資料)
PostgreSQL14の pg_stat_statements 改善(第23回PostgreSQLアンカンファレンス@オンライン 発表資料)PostgreSQL14の pg_stat_statements 改善(第23回PostgreSQLアンカンファレンス@オンライン 発表資料)
PostgreSQL14の pg_stat_statements 改善(第23回PostgreSQLアンカンファレンス@オンライン 発表資料)
 
データベースシステム論07 - SQL基礎演習2 データの問い合わせ
データベースシステム論07 - SQL基礎演習2 データの問い合わせデータベースシステム論07 - SQL基礎演習2 データの問い合わせ
データベースシステム論07 - SQL基礎演習2 データの問い合わせ
 
Machine learning CI/CD with OSS
Machine learning CI/CD with OSSMachine learning CI/CD with OSS
Machine learning CI/CD with OSS
 
固定化か?最新化か?オプティマイザ統計の運用をもう一度考える。 -JPOUG Tech Talk Night #6-
固定化か?最新化か?オプティマイザ統計の運用をもう一度考える。 -JPOUG Tech Talk Night #6-固定化か?最新化か?オプティマイザ統計の運用をもう一度考える。 -JPOUG Tech Talk Night #6-
固定化か?最新化か?オプティマイザ統計の運用をもう一度考える。 -JPOUG Tech Talk Night #6-
 
オープンソースのIoT向けスケールアウト型データベース GridDB 〜性能ベンチマーク結果とOSSを利用したビッグデータ分析環境〜
オープンソースのIoT向けスケールアウト型データベース GridDB 〜性能ベンチマーク結果とOSSを利用したビッグデータ分析環境〜オープンソースのIoT向けスケールアウト型データベース GridDB 〜性能ベンチマーク結果とOSSを利用したビッグデータ分析環境〜
オープンソースのIoT向けスケールアウト型データベース GridDB 〜性能ベンチマーク結果とOSSを利用したビッグデータ分析環境〜
 
Reco choku tech night #09 -reinvent2018報告会-
Reco choku tech night #09 -reinvent2018報告会-Reco choku tech night #09 -reinvent2018報告会-
Reco choku tech night #09 -reinvent2018報告会-
 
Apuri she ji_gaido_d_bmentenansushe_ji__v1.0
Apuri she ji_gaido_d_bmentenansushe_ji__v1.0Apuri she ji_gaido_d_bmentenansushe_ji__v1.0
Apuri she ji_gaido_d_bmentenansushe_ji__v1.0
 
Preview: 世界中のゲーム分析をしてきたPlayFabが大進化!一緒に裏側の最新データ探索の仕組みを覗いてみよう
Preview: 世界中のゲーム分析をしてきたPlayFabが大進化!一緒に裏側の最新データ探索の仕組みを覗いてみようPreview: 世界中のゲーム分析をしてきたPlayFabが大進化!一緒に裏側の最新データ探索の仕組みを覗いてみよう
Preview: 世界中のゲーム分析をしてきたPlayFabが大進化!一緒に裏側の最新データ探索の仕組みを覗いてみよう
 
データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回
 
データベースシステム論09 - SQL応用演習2 ビューとトリガ、アクセス権
データベースシステム論09 - SQL応用演習2 ビューとトリガ、アクセス権データベースシステム論09 - SQL応用演習2 ビューとトリガ、アクセス権
データベースシステム論09 - SQL応用演習2 ビューとトリガ、アクセス権
 
SQLチューニング入門 入門編
SQLチューニング入門 入門編SQLチューニング入門 入門編
SQLチューニング入門 入門編
 

Plus de Kosuke Kida

Plus de Kosuke Kida (8)

Jjugccc2017spring-postgres-ccc_m1
Jjugccc2017spring-postgres-ccc_m1Jjugccc2017spring-postgres-ccc_m1
Jjugccc2017spring-postgres-ccc_m1
 
Oratopostgres-hiroshima
Oratopostgres-hiroshimaOratopostgres-hiroshima
Oratopostgres-hiroshima
 
[OSC2016沖縄]商用DBからPostgreSQLへの移行入門
[OSC2016沖縄]商用DBからPostgreSQLへの移行入門[OSC2016沖縄]商用DBからPostgreSQLへの移行入門
[OSC2016沖縄]商用DBからPostgreSQLへの移行入門
 
商用DBからPostgreSQLへ まず知っておいて欲しいまとめ
商用DBからPostgreSQLへ まず知っておいて欲しいまとめ商用DBからPostgreSQLへ まず知っておいて欲しいまとめ
商用DBからPostgreSQLへ まず知っておいて欲しいまとめ
 
ランナーから見た糖質
ランナーから見た糖質ランナーから見た糖質
ランナーから見た糖質
 
[Postgre sql9.4新機能]レプリケーション・スロットの活用
[Postgre sql9.4新機能]レプリケーション・スロットの活用[Postgre sql9.4新機能]レプリケーション・スロットの活用
[Postgre sql9.4新機能]レプリケーション・スロットの活用
 
まずやっとくPostgreSQLチューニング
まずやっとくPostgreSQLチューニングまずやっとくPostgreSQLチューニング
まずやっとくPostgreSQLチューニング
 
Oss x user_meeting_6_postgres
Oss x user_meeting_6_postgresOss x user_meeting_6_postgres
Oss x user_meeting_6_postgres
 

Dernier

Dernier (10)

知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 

[9.5新機能]追加されたgroupbyの使い方

  • 1. 第6回 PostgreSQLアンカンファレンス 1/21 第6回 PostgreSQLアンカンファレンス [9.5新機能] 追加されたGROUP BY機能の使い方 Kosuke Kida SlideShareへの公開にあたり、2015年12月12日(土)アンカンファレンス当日の発表後に いただいたコメントを元に一部項目を追加しています。 主な追記箇所  P.9  分析系の用途でDB選択時、本機能追加がどう影響するかコメント  P.10- CUBEの実行計画をより分かりやすいものに変更、スライド追加  P.20- 最後に挙げた疑問点のうち、解決の糸口になりそうな情報を発表後の質疑から追記 ※追記個所は本テキストボックスと同色の枠で記載
  • 2. 第6回 PostgreSQLアンカンファレンス 2/21 アジェンダ 9.5の新機能を勉強中のうちの一つを発表してみる ● 標準SQLへの対応 ● 良いところ ● 実用シーンを考察 ● マニュアルにないところの疑問 仕事ではPostgreSQL、Postgres Plusのプリセールス、他DBからの移行評価、環境構築、 トラブル対応などやっています。(PostgreSQLを知らない)顧客対応がほとんどの中で、 どんな情報が有益か考える中で、ベータ版時点から自分で触って、使い方、使いどころを 掴もうと試みています。(Ver9.3ぐらいから)  ・特にアンカンファレンスが開催されるようになって、新機能に対する   初めの一歩のハードルが大きく下がった  ・どういうシーンで使えるかまで考えておくと、お客様からの反応が大きい  ・分析系の用途でPostgreSQLはどこまで使えるか、という相談は最近多いので   BRINインデックスとか、集計構文とか、結構注目されてる
  • 3. 第6回 PostgreSQLアンカンファレンス 3/21 標準SQLへの対応 1クエリで複数の集計を組合せて取得 ● GROUP BY GROUPING SETS ✔ こんな売上実績データ(result表、item表、shop表をJOIN) SELECT r_date::date date,s_name,i_name,r_qt,r_qt * i_price sales FROM result JOIN item ON r_item = i_code JOIN shop ON i_shop = s_id ORDER BY r_date; r_date | s_name | i_name | r_qt | sales ------------+------------+--------------+------+-------- 2015-10-30 | Paul Smith | スラックス | 1 | 20000 2015-10-30 | Dior | シャツ | 2 | 60000 2015-10-30 | Dior | 冬ジャケット | 1 | 100000 2015-10-30 | Paul Smith | シャツ | 1 | 15000 2015-10-31 | DIESEL | ダメージB | 1 | 35000 2015-10-31 | DIESEL | ストレート | 2 | 50000 2015-10-31 | Dior | 冬ジャケット | 1 | 100000 2015-10-31 | Dior | シャツ | 1 | 30000 2015-11-01 | Paul Smith | シャツ | 3 | 45000 2015-11-02 | DIESEL | ダメージA | 1 | 30000
  • 4. 第6回 PostgreSQLアンカンファレンス 4/21 標準SQLへの対応 1クエリで複数の集計を組合せて取得 ● GROUP BY GROUPING SETS ✔ 日別の売上集計と店舗毎の売り上げ集計が欲しい SELECT r_date::date date      ,sum(r_qt * i_price) sum FROM result JOIN item ON r_item = i_code JOIN shop ON i_shop = s_id GROUP BY date ORDER BY sum DESC; date | sum ------------+-------- 2015-10-31 | 215000 2015-10-30 | 195000 2015-11-08 | 50000 2015-11-01 | 45000 2015-11-03 | 45000 2015-11-02 | 45000 2015-11-07 | 40000 2015-11-06 | 30000  : SELECT s_name shop      ,sum(r_qt * i_price) sum FROM result JOIN item ON r_item = i_code JOIN shop ON i_shop = s_id GROUP BY shop ORDER BY sum DESC; shop | sum ------------+-------- Dior | 350000 DIESEL | 195000 Paul Smith | 165000 (3 行)
  • 5. 第6回 PostgreSQLアンカンファレンス 5/21 標準SQLへの対応 1クエリで複数の集計を組合せて取得 ● GROUP BY GROUPING SETS ✔ 1クエリで店舗別、日別、総計を取得 SELECT s_name shop,r_date::date date,sum(r_qt * i_price) sum FROM result JOIN item ON r_item = i_code JOIN shop ON i_shop = s_id GROUP BY GROUPING SETS ((shop),(date),()); shop | date | sum ------------+------------+-------- DIESEL | | 195000 Dior | | 350000 Paul Smith | | 165000 | | 710000 /*総計*/ | 2015-10-30 | 195000 | 2015-10-31 | 215000 | 2015-11-01 | 45000 | 2015-11-02 | 45000 | 2015-11-03 | 45000              :
  • 6. 第6回 PostgreSQLアンカンファレンス 6/21 標準SQLへの対応 1クエリで複数の集計を組合せて取得 ● ROLLUP ✔ 1クエリで店舗-日付の組合せ、店舗別売上、総計を取得 SELECT s_name shop,r_date::date date      ,sum(r_qt * i_price) sum FROM result JOIN item ON r_item = i_code JOIN shop ON i_shop = s_id GROUP BY ROLLUP ((shop),(date)); shop | date | sum ------------+------------+-------- DIESEL | 2015-10-31 | 85000 DIESEL | 2015-11-02 | 30000 DIESEL | 2015-11-06 | 30000 DIESEL | | 195000 Dior | 2015-10-30 | 160000 Dior | 2015-10-31 | 130000 Dior | | 350000 Paul Smith | 2015-10-30 | 35000 Paul Smith | 2015-11-01 | 45000 Paul Smith | 2015-11-02 | 15000 Paul Smith | | 165000 | | 710000 (結果はスライド用にところどころ省略)
  • 7. 第6回 PostgreSQLアンカンファレンス 7/21 標準SQLへの対応 1クエリで複数の集計を組合せて取得 ● CUBE ✔ 1クエリで店舗-日付の組合せ、店舗別売上、日別売上、総計を取得 SELECT s_name shop,r_date::date date      ,sum(r_qt * i_price) sum FROM result JOIN item ON r_item = i_code JOIN shop ON i_shop = s_id GROUP BY CUBE ((shop),(date)); shop | date | sum ------------+------------+-------- DIESEL | 2015-10-31 | 85000 DIESEL | 2015-11-02 | 30000 DIESEL | | 195000 Dior | 2015-10-30 | 160000 Dior | 2015-11-08 | 30000 Dior | | 350000 Paul Smith | 2015-10-30 | 35000 Paul Smith | 2015-11-01 | 45000 Paul Smith | 2015-11-02 | 15000 Paul Smith | 2015-11-08 | 20000 Paul Smith | | 165000 | | 710000 | 2015-10-30 | 195000 | 2015-10-31 | 215000 | 2015-11-08 | 50000 (結果はスライド用にところどころ省略)
  • 8. 第6回 PostgreSQLアンカンファレンス 8/21 良いところ(教科書的な) 1クエリで結果を取得できるので ● APとDBのやりとりの回数を削減 日別集計 店舗別集計 総計 あらゆる組合せ
  • 9. 第6回 PostgreSQLアンカンファレンス 9/21 良いところ(教科書的な) 1クエリで結果を取得できるので ● SeqScanの回数を削減 日別集計 30分 店舗別集計 30分 総計 30分 あらゆる組合せ 1時間 分析用途で現状PostgreSQLが どの程度使えるのか? という問いに対して、回答は、 今のところ、リアルタイム性を どこまで求めるかだと思う。 --- 左記に近い実際にあった例だと、 1日1回、オンライン系のシステム から実績データを取込み、夜間 バッチで加工・集計して、複数の Mビューで保持しとく使い方。 夜間のうちに完了するかどうかが DB選定の肝になっていた。 構文が追加された事による 実行計画の効率化が採用可否の 分岐点になりそうな予感。 --- ※ちなみにOracle EEで限界まで チューニングして同じことをやると 1秒で結果が得られるとか、 それぐらいのスピード感になりそうな話。 「こ、これがリアルタイムか・・・ぐぬぬ」
  • 10. 第6回 PostgreSQLアンカンファレンス 10/21 実用シーンを考察 実行計画はどうなるか ● CUBEの実行計画を確認する               ✔ このテーブルに対して従来の各項目別にGROUP BYすると – 全件のカウント 306.755 ms – アイテム種別カウント 718.326 ms – 売上日別カウント 596.246 ms – 売上店舗別カウント 609.198 ms  計2200 msぐらい ✔ CUBEでは加えて「日別-アイテム別」や「日別-店舗別」等、全組合せ集計結果を取得 -- CUBEのみの実行計画を見たい。 -- JOINの影響をなくすため、類似のデータを単一のテーブルで用意 -- 100万件超えるまで、適当にINSERT INTO huge SELECT * FROM result JOIN item・・・ postgres=# SELECT count(*) FROM huge; count --------- 1310720 postgres=# show work_mem; work_mem ---------- 4MB   -- デフォルト
  • 11. 第6回 PostgreSQLアンカンファレンス 11/21 実用シーンを考察 実行計画はどうなるか ● SeqScanの回数を削減 ✔ ただし、ソートが激増してDISKソートになると劇遅(2.2秒→7.8秒) postgres=# EXPLAIN ANALYZE postgres-# SELECT sales_date::date,shop,kind,count(*) FROM huge postgres-# GROUP BY CUBE ((sales_date::date),(shop),(kind)); QUERY PLAN -------------------------------------------------------------------------------------------------------------------- GroupAggregate (cost=194723.79..566418.36 rows=336 width=26) (actual time=2671.543..7775.091 rows=69 loops=1) Group Key: ((sales_date)::date), shop, kind Group Key: ((sales_date)::date), shop Group Key: ((sales_date)::date) Group Key: () Sort Key: kind, ((sales_date)::date) Group Key: kind, ((sales_date)::date) Group Key: kind Sort Key: shop, kind Group Key: shop, kind Group Key: shop -> Sort (cost=194723.79..198000.59 rows=1310720 width=26) (actual time=2501.926..3181.656 rows=1310720 loops=1) Sort Key: ((sales_date)::date), shop, kind Sort Method: external merge Disk: 42216kB -> Seq Scan on huge (cost=0.00..30182.00 rows=1310720 width=26) (actual time=0.023..290.534 rows=1310720 loops=1) Planning time: 0.141 ms Execution time: 7788.108 ms (17 行)
  • 12. 第6回 PostgreSQLアンカンファレンス 12/21 実用シーンを考察 実行計画はどうなるか ● SeqScanの回数を削減 ✔ ただし、ソートが激増してDISKソートになると劇遅 ✔ work_memの増加で対処(2.2秒→7.8秒→3.0秒) postgres=# set work_mem to '200MB'; SET postgres=# EXPLAIN ANALYZE SELECT sales_date::date,shop,kind,count(*) FROM huge GROUP BY CUBE ((sales_date::date),(shop),(kind)); QUERY PLAN -------------------------------------------------------------------------------------------------------------------- GroupAggregate (cost=163363.79..472338.36 rows=336 width=26) (actual time=1041.637..2986.535 rows=69 loops=1) Group Key: ((sales_date)::date), shop, kind Group Key: ((sales_date)::date), shop Group Key: ((sales_date)::date) Group Key: () Sort Key: kind, ((sales_date)::date) Group Key: kind, ((sales_date)::date) Group Key: kind Sort Key: shop, kind Group Key: shop, kind Group Key: shop -> Sort (cost=163363.79..166640.59 rows=1310720 width=26) (actual time=978.680..1147.774 rows=1310720 loops=1) Sort Key: ((sales_date)::date), shop, kind Sort Method: quicksort Memory: 149662kB -> Seq Scan on huge (cost=0.00..30182.00 rows=1310720 width=26) (actual time=0.030..316.498 rows=1310720 loops=1) Planning time: 0.238 ms Execution time: 3006.193 ms (17 行)
  • 13. 第6回 PostgreSQLアンカンファレンス 13/21 実用シーンを考察 実行計画はどうなるか ● CUBEの実行計画を確認する ✔ このテーブルに対して従来の各項目別にGROUP BYすると – 全件のカウント 306.755 ms – アイテム種別カウント 718.326 ms – 売上日別カウント 596.246 ms – 売上店舗別カウント 609.198 ms  計2200 msぐらい ✔ CUBEでは加えて「日別-アイテム別」や「日別-店舗別」等、全組合せ集計結果を取得 – 全件のカウント – アイテム種別カウント – 売上日別カウント – 売上店舗別カウント – 日別-アイテム別カウント – 日別-店舗別カウント – アイテム別ー店舗別カウント – 日別ーアイテム別ー店舗別カウント   計3000 ms ぐらい
  • 14. 第6回 PostgreSQLアンカンファレンス 14/21 実用シーンを考察 クロス集計までDBで行う ● クロス集計 ✔ 何かのアイテムに関する街頭調査結果みたいなイメージ ✔ それぞれの枠に対してクエリを書いてデータを取得する必要があった ✔ CUBEならこれを1クエリで取得できているので、 あとは「行列変換して表示」できればOKなのだが。 性別 男 女 合計 年代 ~20代 それ以上 ~20代 それ以上 -- アイテムA 10人 10人 80人 100人 200人 アイテムB 20人 10人 50人 80人 160人 アイテムC 30人 10人 50人 50人 140人 合計 60人 30人 180人 230人 500人
  • 15. 第6回 PostgreSQLアンカンファレンス 15/21 実用シーンを考察 1クエリで複数の集計を組合せて取得 ● CUBEでは、クロス集計表を埋める結果はすべて取得済み ✔ 1クエリで店舗-日付の組合せ、店舗別売上、日別売上、総計を取得 SELECT s_name shop,r_date::date date      ,sum(r_qt * i_price) sum FROM result JOIN item ON r_item = i_code JOIN shop ON i_shop = s_id GROUP BY CUBE ((shop),(date)); shop | date | sum ------------+------------+-------- DIESEL | 2015-10-31 | 85000 DIESEL | 2015-11-02 | 30000 DIESEL | | 195000 Dior | 2015-10-30 | 160000 Dior | 2015-11-08 | 30000 Dior | | 350000 Paul Smith | 2015-10-30 | 35000 Paul Smith | 2015-11-01 | 45000 Paul Smith | 2015-11-02 | 15000 Paul Smith | 2015-11-08 | 20000 Paul Smith | | 165000 | | 710000 | 2015-10-30 | 195000 | 2015-10-31 | 215000 | 2015-11-08 | 50000 (結果はスライド用にところどころ省略) shop | date | sum ------------+------------+-------- DIESEL | 2015-10-31 | 85000 DIESEL | 2015-11-02 | 30000 DIESEL | | 195000 Dior | 2015-10-30 | 160000 Dior | 2015-11-08 | 30000 Dior | | 350000 Paul Smith | 2015-10-30 | 35000 Paul Smith | 2015-11-01 | 45000 Paul Smith | 2015-11-02 | 15000 Paul Smith | 2015-11-08 | 20000 Paul Smith | | 165000 | | 710000 | 2015-10-30 | 195000 | 2015-10-31 | 215000 | 2015-11-08 | 50000 (結果はスライド用にところどころ省略)
  • 16. 第6回 PostgreSQLアンカンファレンス 16/21 実用シーンを考察 クロス集計までDBで完結する ● クロス集計 ✔ tablefuncエクステンションでクロス集計 # rpm -ivh postgresql95-contrib-9.5-beta1_1PGDG.el6.x86_64.rpm # psql postgres=# create extension tablefunc; CREATE EXTENSION
  • 17. 第6回 PostgreSQLアンカンファレンス 17/21 実用シーンを考察 クロス集計までDBで完結する ● クロス集計 ✔ tablefuncエクステンションでクロス集計 --CUBE結果をMViewに保存(tablefuncの構文をシンプルにしたいので今回はコレで。) CREATE MATERIALIZED VIEW mv_cube AS SELECT sales_date::date,shop,kind,count(*) FROM result GROUP BY CUBE ((sales_date::date),(shop),(kind)); --crosstab関数をかませて結果を整形 SELECT * FROM crosstab(' SELECT date,COALESCE(shop,''null''),sum FROM mv_cube     --整形したいクエリ ORDER BY date ',' SELECT DISTINCT COALESCE(shop,''null'') shop FROM mv_cube --2番目の引数は ORDER BY shop NULLS LAST --結果の列名に対応 ') AS sales ( date date ,"DIESEL" numeric ,"Dior" numeric ,"Paul Smith" numeric ,"daily sum" numeric );
  • 18. 第6回 PostgreSQLアンカンファレンス 18/21 date | DIESEL | Dior | Paul Smith | daily sum ------------+--------+--------+------------+----------- 2015-10-30 | | 160000 | 35000 | 195000 2015-10-31 | 85000 | 130000 | | 215000 2015-11-01 | | | 45000 | 45000 2015-11-02 | 30000 | | 15000 | 45000 2015-11-03 | 25000 | | 20000 | 45000 2015-11-04 | | 30000 | | 30000 2015-11-05 | | | 15000 | 15000 2015-11-06 | 30000 | | | 30000 2015-11-07 | 25000 | | 15000 | 40000 2015-11-08 | | 30000 | 20000 | 50000 | 195000 | 350000 | 165000 | 710000 (11 行) 実用シーンを考察 クロス集計までDBで完結する ● クロス集計 ✔ tablefuncエクステンションでクロス集計
  • 19. 第6回 PostgreSQLアンカンファレンス 19/21 date | DIESEL | Dior | Paul Smith | daily sum ------------+--------+--------+------------+----------- 2015-10-30 | | 160000 | 35000 | 195000 2015-10-31 | 85000 | 130000 | | 215000 2015-11-01 | | | 45000 | 45000 2015-11-02 | 30000 | | 15000 | 45000 2015-11-03 | 25000 | | 20000 | 45000 2015-11-04 | | 30000 | | 30000 2015-11-05 | | | 15000 | 15000 2015-11-06 | 30000 | | | 30000 2015-11-07 | 25000 | | 15000 | 40000 2015-11-08 | | 30000 | 20000 | 50000 | 195000 | 350000 | 165000 | 710000 (11 行) 実用シーンを考察 クロス集計までDBで完結する ● クロス集計 ✔ tablefuncエクステンションでクロス集計 date | DIESEL | Dior | Paul Smith | daily sum ------------+--------+--------+------------+----------- 2015-10-30 | | 160000 | 35000 | 195000 2015-10-31 | 85000 | 130000 | | 215000 2015-11-01 | | | 45000 | 45000 2015-11-02 | 30000 | | 15000 | 45000 2015-11-03 | 25000 | | 20000 | 45000 2015-11-04 | | 30000 | | 30000 2015-11-05 | | | 15000 | 15000 2015-11-06 | 30000 | | | 30000 2015-11-07 | 25000 | | 15000 | 40000 2015-11-08 | | 30000 | 20000 | 50000 | 195000 | 350000 | 165000 | 710000 (11 行)
  • 20. 第6回 PostgreSQLアンカンファレンス 20/21 マニュアルで見つけられなかった疑問 grouping関数の存在と役割 ● 標準SQLやOracleの構文を見ていると登場するGROUPING関数 ✔ 指定してみたらPostgreSQL 9.5でも使えた ✔ しかしマニュアルに無く、pg_procなどからも定義が探せない SELECT grouping(s_name) AS g1 ,grouping(r_date::date) AS g2 ,grouping(s_name,r_date::date) AS gX ,s_name shop,r_date::date date,sum(r_qt * i_price) sum FROM result JOIN item ON r_item = i_code JOIN shop ON i_shop = s_id GROUP BY GROUPING SETS ((shop),(date),()); g1 | g2 | gx | shop | date | sum ----+----+----+------------+------------+-------- 0 | 1 | 1 | DIESEL | | 195000 0 | 1 | 1 | Dior | | 350000 0 | 1 | 1 | Paul Smith | | 165000 1 | 1 | 3 | | | 710000 1 | 0 | 2 | | 2015-10-30 | 195000 1 | 0 | 2 | | 2015-10-31 | 215000 この実行例が意味をあらわしている? 本当にnullだったか、グルーピングされた結果かどうか gXの3は、2進数の11?項目が増えたら?
  • 21. 第6回 PostgreSQLアンカンファレンス 21/21 マニュアルで見つけられなかった疑問 grouping関数の存在と役割 ● 標準SQLやOracleの構文を見ていると登場するGROUPING関数 ✔ 指定してみたらPostgreSQL 9.5でも使えた ✔ しかしマニュアルに無く、pg_procなどからも定義が探せない – パーサーのソースコード中にそれらしき定義がありそう – http://doxygen.postgresql.org/で検索してみたら、確かにそんな感じ groupingは関数ではなく、構造体?の扱い パーサーのコードの中にありそう 詳細は後日確認します!