zHeap:より優れた制御を提供するためのストレージエンジン
(EDBシニアデータベースアーキテクト、Amit Kapila)

Senior Database Architect
ここ数年、PostgreSQLは、多くのコアシステムの機能、性能、スケーラビリティの点でかなり進歩してきました。 しかし、多くの企業が依然として不満を持っている問題の1つは、時間が経過するにつれてサイズが大きくなることです。これは一般に肥大化と呼ばれます。 私の同僚のRobert Haasは彼のブログの中でそのようなケースをいくつか議論しました。つまり、PostgreSQLのヒープが肥大化する傾向にあること、肥大化を回避するための解決策として「zHeap」と呼ばれるPostgreSQLの新しいストレージフォーマットにEnterpriseDB社が取り組んでいることに言及しました。 このブログ記事では、「zHeap」についてより詳細に説明し、いくつかの実証結果を開示いたします。
PostgreSQLには、専用プロセス(または一連のプロセス)がスペースを利用可能とさせるために、リレーションから削除された行を取り除こうとするオートバキュームというメカニズムがありますが、多くの場合、スペースを完全に再利用することはできません。 PostgreSQLは特に、定期的なバキューム処理やHOTプルーニングによって取り除かなければならないUPDATE操作では新しいバージョンのタプルを常に作成しますが、まだ多くの場合において、スペースが完全に取り戻されることはありません。 DELETE操作されたタプルについても同様の問題が発生します。 これはデータベースの肥大化につながります。 EnterpriseDB社では、肥大化をよりうまく制御する、「zHeap」と呼ばれる新しいストレージ形式の開発を進めています。
このプロジェクトには大きく3つの目的があります。
- 肥大化をよりうまく制御すること。「zHeap」は、一般的な場合にインプレースの更新を許可し、削除または非インプレース更新を実行したトランザクションがコミットすると、すぐにスペースを再利用することによって肥大化を防ぎます。 要するにこの新しいストレージでは、可能な限り、最初の段階で肥大化を避けるのです。
- ヒープページの書き換えを避け、どのインデックスも更新することなしに、インデックスのついた列の更新を可能にすることで、書き込みの増幅を減らすこと。
- タプルヘッダーを縮め、ほとんどのアラインメント・パディングを削除することによって、タプルサイズを縮小すること。
このブログ記事では、主に第1の目的(肥大化に対するより良いコントロールを提供すること)に焦点を当てます。他の目的については、今後別のブログ記事で取り上げます。 新しいタプルが古いタプルよりも大きく、同じページに収めることができない場合や、いくつかの列が変更され、「削除マーキング」がサポートされていないインデックスが使用された場合を除いて、インプレース更新がサポートされます。そのことは「削除マーキング」をサポートするように変更されていないインデックスによりカバーされています。
注意すべきことは、インデックス内の「削除マーキング」をサポートする開発はまだ始まっておらず、我々はまずは、btreeインデックスに対してはサポートしていくということです。 インプレース更新においては、元のタプルをundoログに、新しいタプルをzheapに書き込む必要があります。最新のタプルがまだ可視となっていない場合に、同時実行中の他のトランザクションは、UNDOを用いて古いタプルを読み込む事になります。
DELETE操作では、Insert操作で行うようにTIDを書くことによって切り抜けられますが、undoレコードにタプル全体を書き出します。 これにより、操作を実行したトランザクションがコミットするとすぐに、削除されたレコードが占めるスペースを再利用することができます。 基本的に、DELETE操作が同時実行中のトランザクションに対して可視となっていない場合は、undo、およびheap内からタプルを読み取ることができます。そして、トランザクションがコミットするとすぐにレコードが占有するスペースを再利用することができます。
DELETEと同様に、非インプレース更新操作の結果である古い行のスペースを再利用することができます。 また、タプルの幅を縮小するインプレース更新のためのスペースを即座に再利用したり、挿入または非インプレース更新が元に戻された後に、スペースを再利用したりできます。
以下は、テーブルが絶えず更新されていて、同時に実行時間の長いトランザクションがある場合の、heapテーブルとzheapテーブルのサイズを比較するグラフです。 これらのテストを実行するために、pgbenchを使用してデータを初期化し(スケール係数1000)、シンプルな更新系テスト(1xUPFATE,1xSELECT,1xINSERT) を使用してアップデートを実行しました。 pgbenchの使い方については、PostgreSQLのマニュアルを参照してください。
これらのテストは、x86_64アーキテクチャー、2ソケット、ソケットあたり14コア、コア当たり2スレッド、64GB RAMを搭載したマシンで実行されています。 テスト実行時デフォルト値から変更したパラメタとしては、shared_buffers = 32GB、min_wal_size = 15GB、max_wal_size = 20GB、checkpoint_timeout = 1200、maintenance_work_mem = 1GB、checkpoint_completion_target = 0.9、synchoronous_commit = off です。
以下のグラフは、このテストが更新を実行したテーブルのサイズを示しています。
上記のテストでは、テーブルの最初のサイズがheapで13GB、zheapで11GBであることがわかります。 テストを25分間実行した後(そのうちの最初の15分間はオープン中のトランザクションがあります)、heapのサイズは8クライアントのケースでは16GBに、64クライアントのケースでは20GBに増加しますが、zheapのサイズはテストの最後では両方のケースにおいて、11GBのままです。タプルヘッダーのサイズはzheapの方が小さいため、zheapの初期サイズは小さくなります。 最初の15分間はオートバキュームがオープン中のトランザクションのためにどのスペースも再利用することはできませんが、オープン中だったトランザクションが終了した後でさえ、それを再利用することはできません。 一方、zheapのサイズは一定のままで、生成されたすべてのundoデータは、トランザクションが終了してから数秒以内に削除されます。
以下に、トランザクションがより長い期間にわたって開いたままになっているテストをさらにいくつか紹介します。
テストを40分間実行した後(そのうちの最初の30分間にオープン中のトランザクションが)、heapのサイズは、8クライアントのケースでは19GBに、64クライアントのケースでは26GBに増加しますが、 zheapのサイズは、テスト終了時に両方のケースにおいて11GBのままであり、テスト中に生成されたすべてのundoは、オープン中だったトランザクションが終了してから数秒以内に破棄されます。
テストを55分間実行した後(そのうちの最初の45分間はオープン中のトラザクションがありました)、heapのサイズは8クライアントのケースでは22GBに、64クライアントのケースでは28GBに増加しますが、zheapのサイズは、 テスト終了時に両方のケースにおいて11GBのままであり、テスト中に生成されたすべてのundoは、オープン中だったトランザクションが終了してから数秒以内に破棄されます。
したがって、上記の3つのテストから、heapのサイズは、長時間実行されるトランザクションの同時実行時間が増えるにつれて増加し続けることは明らかです。 heapのサイズはテスト開始時には13GBでしたが、オープントランザクションの期間が15分から30分に、そしてさらに45分に増加すると、64クライアントのカウントテストでは20GB、次に26GB、次に28GBに増加しました。 上記の行についてもう少しテストを行ったところ、オープントランザクションの期間が長くなると、heapのサイズは増加し続けますが、zheapは一定のままであることがわかりました。 たとえば、上記と同様に、70分のテストでトランザクションを60分間OPEN状態にすると、heapのサイズは30GBに増加します。 サイズの増加は、テストの一部として発生している更新の数によっても異なります。
上記の結果は、サイズへの影響だけでなく、zheapのTPS(1秒毎のトランザクション数)も、上記のテストで常により良くなる(最大45%まで)ことに気付きました。 他の高性能マシン上での同様のテストでは、パフォーマンスに関してzheapを使用した方がずっと良い結果を得られています。 このプログはもう長くなってしまいましたので、zheapとheapの生のパフォーマンスに関する詳細については次のブログ投稿で説明したいと思います。 言いたいことは、上記の結果は、すべてのケースでzheapがheapより優れているとは限らないということです。 たとえば、ロールバックのコストはzheapの方が高くなります。 誤解のないように言いますと、このストレージ形式は、現在のheapと並んで別のフォーマットとして提案されているため、ユーザーはユースケースに使用するストレージを決定することができます。
このプロジェクトのコードは公開されており、PG-12からPostgreSQLコミュニティへの機能として提案されています。 Kuntal Ghosh氏に対して、このブログ記事で述べられているパフォーマンステストを行ってくれたことに感謝いたします。
Amit Kapilaは、EnterpriseDBのシニアデータベースアーキテクトです。
[出典:米国EDB公式ホームページ]
▼ 出典URL
https://www.enterprisedb.com/blog/zheap-storage-engine-provide-better-control-over-bloat