データベース運用改善のヒント!コア開発者直伝のPostgreSQL 10の7つの新機能

全国のPostgreSQL使いエンジニアが待ちに待った、バージョン10。新機能の中から、特に“運用”に役立つ7の新機能を、PostgreSQLの専門家、そして開発者である澤田雅彦さんにピックアップして解説してもらいました。

データベース運用改善のヒント!コア開発者直伝のPostgreSQL 10の7つの新機能

2017年10月5日、全国のPostgreSQL使いエンジニアが待ちに待った、バージョン10(安定版)がリリースされました。「今後、自分の開発業務に導入していきたい」と考えている方も多いでしょう。

今回は、PostgreSQLの専門家、そして開発者である澤田雅彦さんに、新機能の中でも特に“運用”に役立つ7の新機能をピックアップして解説してもらいました。これを読めば、現場ですぐに役立つPostgreSQL 10(以下、バージョン10)の知識が身につきます!

<1PostgreSQL: PostgreSQL 10 Released

澤田雅彦(さわだ・まさひこ) 2@sawada_masahiko
2012年、NTTデータに入社。以降、PostgreSQLに関する業務に従事し、主にPostgreSQLの本体開発、技術支援および、国内外問わずさまざまなカンファレンスでの講演活動などを行っている。2016年より、NTT OSSセンタに勤務。PostgreSQLコミュニティでは、Contributorとしてレプリケーション、VACUUM、分散トランザクション機能の開発やバグ修正を通してコア開発に貢献。

(1)テーブルパーティショニング

──まずは、テーブルパーティショニングについてお聞きします。従来のPostgreSQLには、テーブルパーティショニング専用の機能はありませんでした。しかし、バージョン10では、いよいよその機能が搭載されたそうですね。

澤田 はい。これは、ある列の値を元に、テーブルをパーティショニングできる機能です。パーティショニングの方法には2種類があり、ひとつは列の値を「最小値から100」「100から200」というようにレンジで区切り、分割する方法(レンジ・パーティション)。もうひとつは、列の値をリストで区切り、分割する方法(リスト・パーティション)で、これはブログのカテゴリを保持するテーブルを「ミュージックカテゴリ」と「スポーツカテゴリ」でパーティショニングする、というイメージです。サンプルSQLは、以下のようになります。

【サンプルSQL:レンジ・パーティション】

--idをパーティションキーにして、1階層のパーティションテーブルを作成し、データを投入。usersテーブルにINSERTしたデータがちゃんと振り分けられている事を確認する。

-- 1. ユーザIDをパーティションキーにして親テーブルを作成
CREATE TABLE users (id int, name text) PARTITION BY RANGE (id);

-- 2. 各子テーブルを作成
CREATE TABLE users_100 PARTITION OF users FOR VALUES FROM (minvalue) TO (100);
CREATE TABLE users_200 PARTITION OF users FOR VALUES FROM (100) TO (200);

-- 3. ユーザテーブルにデータを挿入
INSERT INTO users VALUES (10, 'Alice'), (50, 'Bob'), (140, 'Carol');

-- 4. テーブルの中身を全て取得
SELECT * FROM users;
 id  | name  
-----+-------
  10 | Alice
  50 | Bob   
 140 | Carol
(3 rows)

-- 5. 各子テーブルを指定して取得。ユーザIDを元に振り分けられていることがわかる
SELECT * FROM users_100;
 id | name
----+-------
 10 | Alice
 50 | Bob
 (2 rows)

SELECT * FROM users_200 ;
 id  | name
-----+-------
 140 | Carol
(1 row)

-- 6. 対応する子テーブルがないとエラー
INSERT INTO users VALUES (250, 'Dave');
ERROR:  no partition of relation "users" found for row
DETAIL:  Partition key of the failing row contains (id) = (250).

【サンプルSQL:リスト・パーティション】

--レンジパーティションと同様の事をするSQLです。

-- 1. ユーザIDをパーティションキーにして親テーブルを作成
CREATE TABLE blogs (id int, category text, content text) PARTITION BY LIST (category);

-- 2. 各子テーブルを作成
CREATE TABLE blogs_music_art PARTITION OF blogs FOR VALUES IN ('music', 'art');
CREATE TABLE blogs_cooking_sports PARTITION OF blogs FOR VALUES IN ('cooking', 'sports');

-- 3. ユーザテーブルにデータを挿入
INSERT INTO blogs VALUES (1, 'music', 'xxxxx'), (2, 'cooking', 'yyyyy'), (3, 'sports', 'zzzzz');

-- 4. 親テーブル経由、各子テーブル経由でテーブル内容を確認する
SELECT * FROM blogs;
 id | category | content
----+----------+---------
  1 | music | xxxxx
  2 | cooking  | yyyyy
  3 | sports   | zzzzz
(3 rows)

SELECT * FROM blogs_cooking_sports;
 id | category | content
----+----------+---------
  2 | cooking  | yyyyy
  3 | sports   | zzzzz
(2 rows)

SELECT * FROM blogs_music_art ;
 id | category | content
----+----------+---------
  1 | music | xxxxx
(1 row)

──「サンプルSQL:レンジ・パーティション」の「6. 対応する子テーブルがないとエラー」でINSERTがエラーになっていますが、これはどうしてですか?

澤田 親テーブルに対しデータをインサートする際、そのデータが格納されるべき適切な子テーブルが存在していなければエラーになってしまうからです。この点は、運用時に注意してください。テーブルに格納するデータがレンジの上限値に達する前に子テーブルを作成する、などの作業を必ず運用フローに組みこむ必要があります。

──どのような用途の場合、テーブルパーティショニングは効果的に機能しますか?

澤田 例えば、100GB以上のデータ量があるような大きなテーブルを分割して、アクセス速度の改善や運用の効率化をするという用途で有効です。それから、日付のレンジパーティショニングで年月ごとに子テーブルを作成し、その年月のテーブルが不要になったらDROPして削除する、といった用途などにも向いていると思います。

──特定のテーブルに全ての年月のデータを入れておき、不要になったデータだけ順次DELETEしていく、という運用ではいけないのでしょうか?

澤田 PostgreSQLって、DELETEしたデータのゴミがずっと残ってしまうので、運用を続けるごとにテーブルがどんどん重くなってしまうんです。年月ごとにテーブルをパーティショニングしておけば、不要になったらDROPできるためゴミデータによるパフォーマンス劣化を防ぐことができます。

3

(2)論理レプリケーション

エンジニアHubに会員登録すると
続きをお読みいただけます(無料)。
登録のメリット
  • すべての過去記事を読める
  • 過去のウェビナー動画を
    視聴できる
  • 企業やエージェントから
    スカウトが届く