🚥

【Postgres】行指向のテーブルと列指向のテーブルを比較する。

2021/10/24に公開

はじめに

最近業務で、RDB にも関わらず、一つのテーブルに一つのカラムを管理しているデータベースを触る機会がありました。
そこで、本来行として持つべきテーブルを、列で持つとどれくらいパフォーマンスに影響を及ぼすのか気になり調べてみました。
データの履歴(バージョン)管理のために、列でデータを持つ必要になる方にも参考になると思います。

環境

% brew info postgresql
postgresql: stable 13.4 (bottled), HEAD

今回実行した SQL

こちらの gitに記載している。

パフォーマンステスト: 行指向テーブル

処理※1 テーブル作成 全件取得 検索 作成 更新 削除
時間(ms)※2 5.7 6.6 1.3 1481.1 7736.5 5502.1
凡その時間(秒) 1 秒以下 1 秒以下 1 秒以下 1 秒 8 秒 6 秒

※1 行数は約 10000 行
※2 小数第二位を四捨五入

パフォーマンステスト: 列指向テーブル

処理※1 テーブル作成 全件取得 検索 作成 更新 削除
時間(ms)※2 22.4 92.6 2.1 15878.8 108352.1 53893.3
凡その時間(秒) 1 秒以下 1 秒以下 1 秒以下 15 秒 108 秒 53 秒

※1 行数は約 10000 行
※2 小数第二位を四捨五入

終わりに

結果的に、列で管理すると相当のパフォーマンス低下に繋がることがわかりました。

注意事項

  • UML のディレクトリでは、ER 図と書いているが、リレーションは記載せず、どのようなテーブルがあるかだけを記載した。
  • SQL のクエリの書き方で大きくパフォーマンスが変わると思われる。

おまけ 1: ログファイルの出力方法

  • ログファイルの設定場所
postgres=# SHOW config_file;
config_file
-----------------------------------------
 /usr/local/var/postgres/postgresql.conf
(1 row)

Time: 0.398 ms
  • ログファイルの場所
/usr/local/var/log
  • ログに時間を設定する方法

Can I log query execution time in PostgreSQL 8.4?

  • ログに出力させたものを grep を使って、外部のログファイルに出力する方法
$ grep "2021-xx-xx 11:50:" postgres.log >> /Users/mac/Psql/ColumnOrientedDatabase/Sql/Insert/Performance/Performance.log

おまけ 2: ログファイルから時間だけを取得するモジュール

下記ディレクトリ(/Users/mac/Psql/ExtractTimeFromPerformanceLog)に、ログファイルから時間だけを取り出すモジュールを作成した。ファイル実行時に、第一引数として該当のログファイルを指定すると、そのログファイルに記載された時間を合計して、出力するようにした。

  • ファイル実行例
$ python3 /Users/mac/Psql/ExtractTimeFromPerformanceLog/ExtractTimeFromPerformanceLog.py /Users/mac/Psql/RowOrientedDatabase/Sql/Delete/Performance/Performance.log
5502.076999999987ms

おまけ 3: ディレクトリ構成

  • ColumnOrientedDatabase と RowOrientedDatabase の sql ディレクトリに、今回のパフォーマンステストで用いた SQL ファイル、SQL を作成するための python のファイル、SQL の実行時間を記載したログファイルを置いている。
  • ExtractTimeFromPerformanceLog.py がおまけ 2 の内容。
$ tree
.
├── ColumnOrientedDatabase
│   ├── Csv
│   │   ├── Output
│   │   │   └── 10000Rows.csv
│   │   └── Process
│   │       └── CreateCsv.py
│   ├── Sql
│   │   ├── CreateTable
│   │   │   ├── Output
│   │   │   │   └── CreateTable.sql
│   │   │   └── Performance
│   │   │       └── Performance.log
│   │   ├── Delete
│   │   │   ├── Output
│   │   │   │   └── Delete.sql
│   │   │   ├── Performance
│   │   │   │   └── Performance.log
│   │   │   └── Process
│   │   │       └── Delete.py
│   │   ├── Insert
│   │   │   ├── Output
│   │   │   │   └── Insert.sql
│   │   │   ├── Performance
│   │   │   │   └── Performance.log
│   │   │   └── Process
│   │   │       └── Insert.py
│   │   ├── Search
│   │   │   ├── Output
│   │   │   │   └── Search.sql
│   │   │   └── Performance
│   │   │       └── Performance.log
│   │   ├── Select
│   │   │   ├── Output
│   │   │   │   └── Select.sql
│   │   │   └── Performance
│   │   │       └── Performance.log
│   │   └── Update
│   │       ├── Output
│   │       │   └── Update.sql
│   │       ├── Performance
│   │       │   └── Performance.log
│   │       └── Process
│   │           └── Update.py
│   └── Uml
│       ├── Er.pu
│       └── Erd.png
├── ExtractTimeFromPerformanceLog
│   └── ExtractTimeFromPerformanceLog.py
├── README.md
└── RowOrientedDatabase
    ├── Csv
    │   ├── Output
    │   │   └── Matrix.csv
    │   └── Process
    │       └── CreateCsvMatrix.py
    ├── Sql
    │   ├── CreateTable
    │   │   ├── Output
    │   │   │   └── CreateTable.sql
    │   │   └── Performance
    │   │       └── Performance.log
    │   ├── Delete
    │   │   ├── Output
    │   │   │   └── Delete.sql
    │   │   ├── Performance
    │   │   │   └── Performance.log
    │   │   └── Process
    │   │       └── Delete.py
    │   ├── Insert
    │   │   ├── Output
    │   │   │   └── Insert.sql
    │   │   ├── Performance
    │   │   │   └── Performance.log
    │   │   └── Process
    │   │       └── Insert.py
    │   ├── Search
    │   │   ├── Output
    │   │   │   └── Search.sql
    │   │   └── Performance
    │   │       └── Performance.log
    │   ├── Select
    │   │   ├── Output
    │   │   │   └── Select.sql
    │   │   └── Performance
    │   │       └── Performance.log
    │   └── Update
    │       ├── Output
    │       │   └── Update.sql
    │       ├── Performance
    │       │   └── Performance.log
    │       └── Process
    │           └── Update.py
    └── Uml
        ├── Er.pu
        └── Erd.png

55 directories, 40 files

Discussion