HammerDB で RDBMS のベンチマークを取ってみる(PostgreSQL編)

RDBMS のベンチマークテストツールである HammerDB で PostgreSQL のテストを行う手順を纏めてみました。

ウィスキー、シガー、パイプをこよなく愛する大栗です。

最近 RDBMS のパフォーマンスを計測する機会があったので、手順をまとめておこうと思います。以前のエントリなどではJdbcRunnerを使用することが多かったのですが、今回は別のツールである HammerDB を使用しました。このエントリーでは PostgreSQL を対象としたベンチマークを実施します。

MySQL 版も書きました。MySQL での手順を確認したい方は、以下のエントリを御覧ください。

HammerDB

HammerDB は[Steve Shaw]氏を中心として開発を行っており、トランザクション処理性能評議会(TPC)がサポートしているオープンソースのデータベースベンチマークアプリケーションです。HammerDB では世界的に利用者が多い以下のデータベースをサポートしています。

  • Oracle (TimesTen)
  • SQL Server
  • Db2
  • MySQL (Amazon Aurora)
  • PostgreSQL (ExterpriseDB / Amazon Redshift / Greenplum)
  • MariaDB

サポートしているベンチマーク指標は以下のものになります。将来的に TPC-E をサポートする計画もあるようです。

  • TPROC-C
    • TPC-C の派生ベンチマーク
    • オンライントランザクション処理 (OLTP) のベンチマークで卸売業者の業務モデルを模しています
    • 詳細はドキュメントを参照
  • TPROC-H
    • TPC-H の派生ベンチマーク
    • 意思決定支援ベンチマークで、大量のデータを調査し、複雑なクエリを実行します
    • 詳細はドキュメントを参照

やってみる

注意
ベンチマーク結果は、データベース・ソフトウェアや提供環境により実施や公開が制限されている場合があります。例えば Oracle ではベンチマークテストの結果は公開を禁じられています。AWS では AWS Service Terms の 1.8 に準じる必要があります。

事前準備

ベンチマークの環境は以下としています。

  • HammerDB : version 4.3
  • クライアント環境
    • AMI : ami-08a8688fb7eacb171 (amzn2-ami-kernel-5.10-hvm-2.0.20220207.1-x86_64-gp2)
    • OS : Amazon Linux 2
    • psql (PostgreSQL) 13.3
  • データベース環境
    • PostgreSQL 13

また、クライアントからデータベースへのネットワーク接続が問題なく出来ることとします。

Extras Library の PostgreSQL 13 を有効化します。

$ sudo amazon-linux-extras enable postgresql13

postgresqlpostgresql-develをインストールします。

$ sudo yum clean metadata && sudo yum install -y postgresql postgresql-devel

HammerDB をダウンロードします。

$ wget https://github.com/TPC-Council/HammerDB/releases/download/v4.3/HammerDB-4.3-Linux.tar.gz

ダウンロードしたファイルを解凍します。

$ tar xvfz HammerDB-4.3-Linux.tar.gz

解凍したディレクトリへ移動します。

$ cd HammerDB-4.3

HammerDB の CLI を起動します。

$ ./hammerdbcli

librarycheckコマンドでライブラリのインストール状況をチェックします。出力される結果の中で、PostgreSQL の内容がSuccessになっていることを確認します。

hammerdb>librarycheck
Checking database library for Oracle
・
・
・
Checking database library for PostgreSQL
Success ... loaded library Pgtcl for PostgreSQL
・
・
・

一旦 HammerDB CLI を終了します。

hammerdb>exit

TPROC-C の実施

TPC-C の派生ベンチマークである TPROC-C を実行してみます

HammerDB の CLI を起動します。

$ ./hammerdbcli

対象データベースを PostgreSQL に設定し、ベンチマークを TPROC-C に設定します。

hammerdb>dbset db pg
hammerdb>dbset bm TPROC-C

設定内容を確認します。この内容について必要な項目を設定していきます。

hammerdb>print dict
Dictionary Settings for PostgreSQL
connection {
 pg_host    = localhost
 pg_port    = 5432
 pg_sslmode = prefer
}
tpcc       {
 pg_count_ware       = 1
 pg_num_vu           = 1
 pg_superuser        = postgres
 pg_superuserpass    = postgres
 pg_defaultdbase     = postgres
 pg_user             = tpcc
 pg_pass             = tpcc
 pg_dbase            = tpcc
 pg_tspace           = pg_default
 pg_vacuum           = false
 pg_dritasnap        = false
 pg_oracompat        = false
 pg_storedprocs      = false
 pg_partition        = false
 pg_total_iterations = 10000000
 pg_raiseerror       = false
 pg_keyandthink      = false
 pg_driver           = test
 pg_rampup           = 2
 pg_duration         = 5
 pg_allwarehouse     = false
 pg_timeprofile      = false
 pg_async_scale      = false
 pg_async_client     = 10
 pg_async_verbose    = false
 pg_async_delay      = 1000
 pg_connect_pool     = false
}

接続先のホスト名と接続ポートを設定します。

hammerdb>diset connection pg_host xxxxxxxxxxxx.example.com
hammerdb>diset connection pg_port 99999

管理者ユーザ名、管理者パスワード、初期接続先のデータベースを入力します。

hammerdb>diset tpcc pg_superuser XXXXX
hammerdb>diset tpcc pg_superuserpass XXXXXXXXXXXXXXXX
hammerdb>diset tpcc pg_defaultdbase sampledb

必要に応じて、ベンチマークを実行する際のユーザ名、パスワード、データベースを入力します。ここで設定するユーザとデータベースは存在しない場合管理者ユーザを使用して自動で作成されます。

hammerdb>diset tpcc pg_user tpcc
hammerdb>diset tpcc pg_pass tpcc
hammerdb>diset tpcc pg_dbase tpcc

warehouse を指定します。倉庫を表し、データベース全体のサイズを決める因子になっています。

hammerdb>diset tpcc pg_count_ware 100

データロード時の同時実行数を指定します。

hammerdb>diset tpcc pg_num_vu 4

設定した内容を確認します。

hammerdb>print dict
Dictionary Settings for PostgreSQL
connection {
 pg_host    = xxxxxxxxxxxx.example.com
 pg_port    = 99999
 pg_sslmode = prefer
}
tpcc       {
 pg_count_ware       = 100
 pg_num_vu           = 4
 pg_superuser        = XXXXX
 pg_superuserpass    = XXXXXXXXXXXXXXXX
 pg_defaultdbase     = sampledb
 pg_user             = tpcc
 pg_pass             = tpcc
 pg_dbase            = tpcc
 pg_tspace           = pg_default
 pg_vacuum           = false
 pg_dritasnap        = false
 pg_oracompat        = false
 pg_storedprocs      = false
 pg_partition        = false
 pg_total_iterations = 10000000
 pg_raiseerror       = false
 pg_keyandthink      = false
 pg_driver           = test
 pg_rampup           = 2
 pg_duration         = 5
 pg_allwarehouse     = false
 pg_timeprofile      = false
 pg_async_scale      = false
 pg_async_client     = 10
 pg_async_verbose    = false
 pg_async_delay      = 1000
 pg_connect_pool     = false
}

ベンチマーク用のスキーマとデータを作成します。

hammerdb>buildschema

データの作成が完了すると、以下のようなメッセージが表示されます。一度改行するとhammerdb>のプロンプトに戻ります。

Vuser 1:TPCC SCHEMA COMPLETE
Vuser 1:FINISHED SUCCESS
ALL VIRTUAL USERS COMPLETE

データを作成したときの仮想ユーザを削除します。

hammerdb>vudestroy

次にベンチマークの実施設定を行います。ベンチマークの実施時はドライバスクリプトの設定をtimedにします。

hammerdb>diset tpcc pg_driver timed

クライアント側のタイムプロファイルを有効にします。

hammerdb>diset tpcc pg_timeprofile true

dbset と diset で設定した内容をロードします

hammerdb>loadscript

仮想ユーザの構成を確認します。

hammerdb>print vuconf
Virtual Users = 5
User Delay(ms) = 500
Repeat Delay(ms) = 500
Iterations = 1
Show Output = 1
Log Output = 0
Unique Log Name = 0
No Log Buffer = 0
Log Timestamps = 0

設定項目を確認します。

hammerdb>vuset
Usage: vuset [vu|delay|repeat|iterations|showoutput|logtotemp|unique|nobuff|timestamps] value

ベンチマークを実行する同時実行ユーザー数を定義します。ここでは 8 にしています。

hammerdb>vuset vu 8

ログを出力する設定を行います。

hammerdb>vuset logtotemp 1

ログ名の設定

hammerdb>vuset unique 1

ログへのタイムスタンプ設定を行います。

hammerdb>vuset timestamps 1

実施した設定を確認します。

hammerdb>print vuconf
Virtual Users = 8
User Delay(ms) = 500
Repeat Delay(ms) = 500
Iterations = 1
Show Output = 1
Log Output = 1
Unique Log Name = 1
No Log Buffer = 0
Log Timestamps = 1

ベンチマークの実行ユーザを作成します。出力されるログのパスも表示されます。

hammerdb>vucreate
Vuser 1 created MONITOR - WAIT IDLE
Vuser 2 created - WAIT IDLE
Vuser 3 created - WAIT IDLE
Vuser 4 created - WAIT IDLE
Vuser 5 created - WAIT IDLE
Vuser 6 created - WAIT IDLE
Vuser 7 created - WAIT IDLE
Vuser 8 created - WAIT IDLE
Vuser 9 created - WAIT IDLE
Logging activated
to /tmp/hammerdb_1234ABCD5678EFGH1234ABCD.log
9 Virtual Users Created with Monitor VU

実行ユーザのステータスを確認します。各ユーザのステータスがWAIT IDLEになっていることを確認します。

hammerdb>vustatus
1 = WAIT IDLE
2 = WAIT IDLE
3 = WAIT IDLE
4 = WAIT IDLE
5 = WAIT IDLE
6 = WAIT IDLE
7 = WAIT IDLE
8 = WAIT IDLE
9 = WAIT IDLE

ベンチマークを実行します。

hammerdb>vurun
Vuser 1:RUNNING
Vuser 1:Initializing xtprof time profiler
Vuser 1:Beginning rampup time of 2 minutes
・
・
・

ALL VIRTUAL USERS COMPLETEが表示されるとベンチマークの完了です。TEST RESULTの行に結果が出力されます。また時間情報が出力されたログのパスも出力されています。

結果にはNOPMTPMがあります。NOPM は New Orders per Minute の略で、新規発注処理を1分間に何回できたかを表しています。TPC-C の場合は分間の新規発注処理数を tpmC で表しますが、HammerDB では 厳密には TPC-C に準拠していないため使用できません。そのため NOPM という指標を使用しています。TPM は Transactions per Minute の略で、オンライン トランザクション カウンターに表示される値で異なるデータベース間では比較できません。

Vuser 1:Test complete, Taking end Transaction Count.
Vuser 1:8 Active Virtual Users configured
Vuser 1:TEST RESULT : System achieved 99999 NOPM from 99999 PostgreSQL TPM
Vuser 1:Gathering timing data from Active Virtual Users...
Vuser 4:FINISHED SUCCESS
Vuser 5:FINISHED SUCCESS
Vuser 2:FINISHED SUCCESS
Vuser 9:FINISHED SUCCESS
Vuser 3:FINISHED SUCCESS
Vuser 7:FINISHED SUCCESS
Vuser 6:FINISHED SUCCESS
Vuser 8:FINISHED SUCCESS
Vuser 1:Calculating timings...
Vuser 1:Writing timing data to /tmp/hdbxtprofile.log
Vuser 1:FINISHED SUCCESS
ALL VIRTUAL USERS COMPLETE

ログの中身を確認します。各実行ユーザの結果詳細が出力されており、一番最後に各オペレーションの全体結果が出力されます。

$ cat /tmp/hdbxtprofile.log
PostgreSQL Hammerdb Time Profile Report @ Wed Feb 09 09:51:40 UTC 2022
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>>>>> VIRTUAL USER 2 : ELAPSED TIME : 999999ms
>>>>> PROC: NEWORD
・
・
・
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>>>>> SUMMARY OF 8 ACTIVE VIRTUAL USERS : MEDIAN ELAPSED TIME : 999999ms
>>>>> PROC: NEWORD
CALLS: 999999   MIN: 9.999ms    AVG: 9.999ms    MAX: 999.999ms  TOTAL: 9999999.999ms
P99: 99.999ms   P95: 9.999ms    P50: 9.999ms    SD: 9999.999    RATIO: 99.999%
>>>>> PROC: PAYMENT
CALLS: 999999   MIN: 9.999ms    AVG: 9.999ms    MAX: 999.999ms  TOTAL: 9999999.999ms
P99: 99.999ms   P95: 9.999ms    P50: 9.999ms    SD: 9999.999    RATIO: 99.999%
>>>>> PROC: DELIVERY
CALLS: 999999   MIN: 9.999ms    AVG: 9.999ms    MAX: 999.999ms  TOTAL: 9999999.999ms
P99: 99.999ms   P95: 9.999ms    P50: 9.999ms    SD: 9999.999    RATIO: 99.999%
>>>>> PROC: SLEV
CALLS: 999999   MIN: 9.999ms    AVG: 9.999ms    MAX: 999.999ms  TOTAL: 9999999.999ms
P99: 99.999ms   P95: 9.999ms    P50: 9.999ms    SD: 9999.999    RATIO: 99.999%
>>>>> PROC: OSTAT
CALLS: 999999   MIN: 9.999ms    AVG: 9.999ms    MAX: 999.999ms  TOTAL: 9999999.999ms
P99: 99.999ms   P95: 9.999ms    P50: 9.999ms    SD: 9999.999    RATIO: 99.999%
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

TPROC-H の実施

TPC-H の派生ベンチマークである TPROC-H を実行してみます

HammerDB の CLI を起動します。

$ ./hammerdbcli

対象データベースを PostgreSQL に設定し、ベンチマークを TPROC-H に設定します。

hammerdb>dbset db pg
hammerdb>dbset bm TPROC-H

設定内容を確認します。この内容について必要な項目を設定していきます。

hammerdb>print dict
Dictionary Settings for PostgreSQL
connection {
 pg_host    = localhost
 pg_port    = 5432
 pg_sslmode = prefer
}
tpch       {
 pg_scale_fact         = 1
 pg_tpch_superuser     = postgres
 pg_tpch_superuserpass = postgres
 pg_tpch_defaultdbase  = postgres
 pg_tpch_user          = tpch
 pg_tpch_pass          = tpch
 pg_tpch_dbase         = tpch
 pg_tpch_tspace        = pg_default
 pg_tpch_gpcompat      = false
 pg_tpch_gpcompress    = false
 pg_num_tpch_threads   = 1
 pg_total_querysets    = 1
 pg_raise_query_error  = false
 pg_verbose            = false
 pg_refresh_on         = false
 pg_degree_of_parallel = 2
 pg_update_sets        = 1
 pg_trickle_refresh    = 1000
 pg_refresh_verbose    = false
 pg_cloud_query        = false
 pg_rs_compat          = false
}

接続先のホスト名と接続ポートを設定します。

hammerdb>diset connection pg_host xxxxxxxxxxxx.example.com
hammerdb>diset connection pg_port 99999

管理者ユーザ名、管理者パスワード、初期接続先のデータベースを入力します。

hammerdb>diset tpch pg_tpch_superuser XXXXX
hammerdb>diset tpch pg_tpch_superuserpass XXXXXXXXXXXXXXXX
hammerdb>diset tpch pg_tpch_defaultdbase sampledb

必要に応じて、ベンチマークを実行する際のユーザ名、パスワード、データベースを入力します。ここで設定するユーザとデータベースは存在しない場合管理者ユーザを使用して自動で作成されます。

hammerdb>diset tpch pg_tpch_user tpch
hammerdb>diset tpch pg_tpch_pass tpch
hammerdb>diset tpch pg_tpch_dbase tpch

pg_scale_fact を指定します。データのサイズです。以下の値のいずれかを入力します。

1, 10, 30, 100, 300, 1000, 3000, 10000, 30000, 100000

hammerdb>diset tpch pg_scale_fact 100

データロード時の同時実行数を指定します。

hammerdb>diset tpch pg_num_tpch_threads 4

設定した内容を確認します。

hammerdb>print dict
Dictionary Settings for PostgreSQL
connection {
 pg_host    = xxxxxxxxxxxx.example.com
 pg_port    = 99999
 pg_sslmode = prefer
}
tpch       {
 pg_scale_fact         = 100
 pg_tpch_superuser     = XXXXX
 pg_tpch_superuserpass = XXXXXXXXXXXXXXXX
 pg_tpch_defaultdbase  = sampledb
 pg_tpch_user          = tpch
 pg_tpch_pass          = tpch
 pg_tpch_dbase         = tpch
 pg_tpch_tspace        = pg_default
 pg_tpch_gpcompat      = false
 pg_tpch_gpcompress    = false
 pg_num_tpch_threads   = 1
 pg_total_querysets    = 1
 pg_raise_query_error  = false
 pg_verbose            = false
 pg_refresh_on         = false
 pg_degree_of_parallel = 2
 pg_update_sets        = 1
 pg_trickle_refresh    = 1000
 pg_refresh_verbose    = false
 pg_cloud_query        = false
 pg_rs_compat          = false
}

ベンチマーク用のスキーマとデータを作成します。

hammerdb>buildschema

データの作成が完了すると、以下のようなメッセージが表示されます。一度改行するとhammerdb>のプロンプトに戻ります。

Vuser 1:TPCH SCHEMA COMPLETE
Vuser 1:FINISHED SUCCESS
ALL VIRTUAL USERS COMPLETE
TPROC-H Driver Script

データを作成したときの仮想ユーザを削除します。

hammerdb>vudestroy

dbset と diset で設定した内容をロードします

hammerdb>loadscript

仮想ユーザの構成を確認します。

hammerdb>print vuconf
Virtual Users = 5
User Delay(ms) = 500
Repeat Delay(ms) = 500
Iterations = 1
Show Output = 1
Log Output = 0
Unique Log Name = 0
No Log Buffer = 0
Log Timestamps = 0

ベンチマークを実行する同時実行ユーザー数を定義します。ここでは 1 にしています。

hammerdb>vuset vu 1

ログを出力する設定を行います。

hammerdb>vuset logtotemp 1

ログ名の設定

hammerdb>vuset unique 1

実施した設定を確認します。

hammerdb>print vuconf
Virtual Users = 1
User Delay(ms) = 500
Repeat Delay(ms) = 500
Iterations = 1
Show Output = 1
Log Output = 1
Unique Log Name = 1
No Log Buffer = 0
Log Timestamps = 0

ベンチマークの実行ユーザを作成します。出力されるログのパスも表示されます。

hammerdb>vucreate
Vuser 1 created - WAIT IDLE
Logging activated
to /tmp/hammerdb_ABCD1234EFGH5678IJKM1234.log
1 Virtual Users Created

実行ユーザのステータスを確認します。各ユーザのステータスがWAIT IDLEになっていることを確認します。

hammerdb>vustatus
1 = WAIT IDLE

ベンチマークを実行します。

hammerdb>vurun
Vuser 1:RUNNING
Vuser 1:Executing Query 14 (1 of 22)
・
・
・
Vuser 1:Completed 1 query set(s) in 99 seconds
Vuser 1:Geometric mean of query times returning rows (22) is 9.99999
Vuser 1:FINISHED SUCCESS
ALL VIRTUAL USERS COMPLETE
TPROC-H Driver Script

ログの中身を確認します。各クエリの実行時間が出力されています。TPC-H では QphH@Size という 1時間当たりの複合クエリのパフォーマンスを指標にしたものを使用しますが、HammerDB では派生の TPROC-H を使用しているため使用できません。結果を評価するにはクエリの実行時間を個別に比較するなどが良いかもしれません。

$ cat /tmp/hammerdb_ABCD1234EFGH5678IJKM1234.log
Hammerdb Log @ Wed Feb 09 14:08:34 UTC 2022
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Vuser 1:Executing Query 14 (1 of 22)
Vuser 1:query 14 completed in 0.999 seconds
Vuser 1:Executing Query 2 (2 of 22)
Vuser 1:query 2 completed in 0.999 seconds
Vuser 1:Executing Query 9 (3 of 22)
Vuser 1:query 9 completed in 0.999 seconds
Vuser 1:Executing Query 20 (4 of 22)
Vuser 1:query 20 completed in 0.999 seconds
Vuser 1:Executing Query 6 (5 of 22)
Vuser 1:query 6 completed in 0.999 seconds
Vuser 1:Executing Query 17 (6 of 22)
Vuser 1:query 17 completed in 0.999 seconds
Vuser 1:Executing Query 18 (7 of 22)
Vuser 1:query 18 completed in 0.999 seconds
Vuser 1:Executing Query 8 (8 of 22)
Vuser 1:query 8 completed in 0.999 seconds
Vuser 1:Executing Query 21 (9 of 22)
Vuser 1:query 21 completed in 0.999 seconds
Vuser 1:Executing Query 13 (10 of 22)
Vuser 1:query 13 completed in 0.999 seconds
Vuser 1:Executing Query 3 (11 of 22)
Vuser 1:query 3 completed in 0.999 seconds
Vuser 1:Executing Query 22 (12 of 22)
Vuser 1:query 22 completed in 0.999 seconds
Vuser 1:Executing Query 16 (13 of 22)
Vuser 1:query 16 completed in 0.999 seconds
Vuser 1:Executing Query 4 (14 of 22)
Vuser 1:query 4 completed in 0.999 seconds
Vuser 1:Executing Query 11 (15 of 22)
Vuser 1:query 11 completed in 0.999 seconds
Vuser 1:Executing Query 15 (16 of 22)
Vuser 1:query 15 completed in 0.999 seconds
Vuser 1:Executing Query 1 (17 of 22)
Vuser 1:query 1 completed in 0.999 seconds
Vuser 1:Executing Query 10 (18 of 22)
Vuser 1:query 10 completed in 0.999 seconds
Vuser 1:Executing Query 19 (19 of 22)
Vuser 1:query 19 completed in 0.999 seconds
Vuser 1:Executing Query 5 (20 of 22)
Vuser 1:query 5 completed in 0.999 seconds
Vuser 1:Executing Query 7 (21 of 22)
Vuser 1:query 7 completed in 0.999 seconds
Vuser 1:Executing Query 12 (22 of 22)
Vuser 1:query 12 completed in 0.999 seconds
Vuser 1:Completed 1 query set(s) in 99 seconds
Vuser 1:Geometric mean of query times returning rows (22) is 0.99999

さいごに

HammerDB は、OLTP と OLAP の両方のベンチマークを簡単に行えるツールです。使用するデータベースのパフォーマンスは実ワークロードで確認するのが最適なのですが、なかなか実施するのは難しいです。そのため HammerDB のようなベンチマークテストツールを使用して必要なパフォーマンスを発揮するかの目安を確認すると良いのではないでしょうか。