PostgreSQL のアライメントについて検証してみた

こんにちは。サイオステクノロジー OSS サポート担当 Y です。

今回は PostgreSQL のアライメントについて検証してみました。(※以下の内容は PostgreSQL 10.1 及び CentOS 7.4 にて検証/調査しています。)

■はじめに

正直な所私自身がまだ良く理解できていないのですが、PostgreSQL のテーブルに格納されるレコードのデータは “アライメント” と呼ばれる境界を跨がないように格納されており、この境界を跨がないようにするために、余った領域はパディングされる作りになっているらしいです。

また、このアライメントを意識してテーブル設計を行うと、パディングの量を減らすことでテーブルの容量を節約できる可能性があるらしいです。

上記のようなお話をとあるセミナーで聞かせて頂いたので、実際に自分でも検証してみました。

■検証

まず、アライメントの値はプラットフォームに依存しているらしいので、以下のように pg_controldata コマンドにて当該環境のアライメントの値を確認します。

上記 pg_controldata コマンドの出力によると、今回検証した環境の場合アライメントの値は “8” になっているようなので、データの格納領域のイメージとしては以下ような 8 byte 区切りの領域になります。

例えば int 型 (4 byte) のデータを格納した場合は以下のようなイメージになります。

また、int 型 (4 byte) のデータを 2つ格納した場合は以下のようなイメージになります。

上記イメージだけだとわかり辛いので、実際に検証を行いテーブルのサイズ等を確認してみます。

検証用に int 型 (4 byte) 2つ, bigint 型 (8 byte) 2つの計 4つのカラムを持つテーブルを 2つ用意します。

この 2つのテーブルの違いは “カラムの順序” です。

テーブル “hoge” は int, int, bigint, bigint の順でカラムを定義しています。

また、テーブル “fuga” は int, bigint, int, bigint の順でカラムを定義しています。

これらのテーブルにレコードが格納された際のイメージは以下のようになり、”hoge” と “fuga” で 1レコードで利用される領域の大きさが異なる状況になります。

実際に内容が全く同じレコードを 100万レコードずつ INSERT し、各テーブルのサイズを確認してみると、”fuga” の方がテーブルのサイズが大きくなる結果となりました。

次に、以下のようにカラム数が違うテーブルでの検証も行なってみました。

これらのテーブルにレコードが格納された際のイメージは以下のようになり、”foo” と “bar” で 1レコードで利用される領域の大きさは同じになっています。

実際に内容が全く同じレコードを 100万レコードずつ INSERT し、各テーブルのサイズを確認してみると、カラム数が異なるテーブルであるにもかかわらず 2つのテーブルのサイズは同じになっていました。

上記の通り、同じカラムを定義していても順序によってテーブルのサイズが変わる場合や、異なるカラムを定義していても順序によってテーブルのサイズが同じになることがあるようです。

また、各データ型のアライメントについては、システムカタログ pg_type の typalign 列で確認できるようです。

(https://www.postgresql.org/docs/10/static/catalog-pg-type.html)

■最後に

かなり細かい内容ですが、設計時にカラムの順序を調整することでテーブルサイズを削減することができる可能性もあるようです。大規模なデータを扱う環境で PostgreSQL を採用する場合は、アライメントを気にしてみると少し幸せになれるかもしれません。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメント投稿

メールアドレスは表示されません。


*