テーブル作成

どうもこんにちは。ilovegpdbです。

前回が力みすぎたので今日は気軽に行きます。

テーブルをつくって遊ぶ

インストールしたはいいけどテーブルがないと何もできないですね。
SQLはだいたいPostgreSQLと同じなのでPostgreSQL使ったことがあると何かと便利ですよ。

-- テーブルを作る
CREATE TABLE sales(
  order_no bigint,
  product_code char(8),
  sales_time timestamp
) DISTRIBUTED BY (order_no);

みたいな感じにしてみました。あくまで例です。
CREATE TABLEと列定義は標準SQLとほぼ互換なので問題ないですね。後ろにDISTRIBUTED BY句がついています。Greenplumはシェアードナッシングのデータベースなので、セグメントサーバが一つのテーブルを水平分割して持ちます。このときの分散ポリシーをテーブル毎に決定できるわけです。キーはハッシュ関数にかけられてその結果で保存ノードが決まります。ハッシュテーブルのバケットがノードになった感じですね。ちなみにDISTRIBUTED RANDOMLYを指定すると完全にランダムに(ラウンドロビンで)分散されます。一見素敵な分散ポリシーに見えますが、分散キーはクエリの性能を左右するので決めておくことが重要です。そのうちわかります。

SELECT

db1=# INSERT INTO sales SELECT order_no, lpad((order_no / 2)::text || (order_no % 10), 8, '0'), '2010-01-01 00:00:00'::timestamp + ('' || order_no || 'min')::interval FROM generate_series(1, 1000000)order_no;
INSERT 0 1000000
Time: 7583.776 ms

generate_series()もPostgreSQLと同様に使えるので便利ですね。

db1=# SELECT * FROM sales LIMIT 10;
 order_no | product_code |     sales_time      
----------+--------------+---------------------
        1 | 00000001     | 2010-01-01 00:01:00
        3 | 00000013     | 2010-01-01 00:03:00
        5 | 00000025     | 2010-01-01 00:05:00
        7 | 00000037     | 2010-01-01 00:07:00
        9 | 00000049     | 2010-01-01 00:09:00
       11 | 00000051     | 2010-01-01 00:11:00
       13 | 00000063     | 2010-01-01 00:13:00
       15 | 00000075     | 2010-01-01 00:15:00
       17 | 00000087     | 2010-01-01 00:17:00
       19 | 00000099     | 2010-01-01 00:19:00
(10 rows)

Time: 10.978 ms
db1=# SELECT count(*), avg(substr(product_code, 4, 4)::int) FROM sales;
  count  |  avg   
---------+--------
 1000000 | 4999.5
(1 row)

Time: 399.057 ms

集計機能も問題なし。EXPLAINしてみます。

db1=# EXPLAIN ANALYZE SELECT count(*), avg(substr(product_code, 4, 4)::int) FROM sales;
                                                                         QUERY PLAN                                                                         
------------------------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=16845.37..16845.38 rows=1 width=9)
   Rows out:  1 rows with 1694 ms to end, start offset by 0.372 ms.
   Executor memory:  8K bytes.
   ->  Gather Motion 2:1  (slice1; segments: 2)  (cost=16845.31..16845.35 rows=1 width=9)
         Rows out:  2 rows at destination with 1677 ms to first row, 1694 ms to end, start offset by 0.375 ms.
         ->  Aggregate  (cost=16845.31..16845.32 rows=1 width=9)
               Rows out:  Avg 1.0 rows x 2 workers.  Max 1 rows (seg0) with 1693 ms to end, start offset by 0.716 ms.
               Executor memory:  8K bytes avg, 8K bytes max (seg0).
               ->  Seq Scan on sales  (cost=0.00..11842.20 rows=500310 width=9)
                     Rows out:  Avg 500000.0 rows x 2 workers.  Max 500001 rows (seg0) with 0.036 ms to first row, 674 ms to end, start offset by 0.717 ms.
 Slice statistics:
   (slice0)    Executor memory: 221K bytes.
   (slice1)    Executor memory: 240K bytes avg x 2 workers, 240K bytes max (seg0).
 Total runtime: 1694.183 ms
(14 rows)

Time: 1695.052 ms

二段で集計している様子が伺えますね。Greenplumはセグメントサーバを並列処理させることでクエリの高速化を図ります。分散集計はまさにこの典型で、いったんセグメント内で集計してからマスタサーバにかき集めて再集計しているようです。

まとめ

とりあえずSQLを実行しました。簡単なSQLの実行を確認できました。
ちなみに今回からxlargeインスタンスを使うことにしましたので、もう少し1ノードでセグメント数を増やしてみたいと思います。また、PostgreSQL単体の処理と比較してどのぐらい違うか比べてみたいです。