Sysbench は、オープンソースでモジュール化され、クロスプラットフォーム対応・マルチスレッドの性能テストツールです。データベース、CPU、メモリ、スレッド、I/O のパフォーマンスを評価できます。MySQL、Oracle、PostgreSQL データベースをサポートしています。本ドキュメントでは、PolarDB-X 1.0 インスタンスに対して、オンライントランザクション処理(OLTP)および SELECT シナリオにおける Sysbench ストレストテストの実行方法を説明し、4 種類のインスタンスエディションごとのベンチマーク結果を提供します。
テスト環境
すべてのインスタンスは同一ゾーンおよび同一 Virtual Private Cloud(VPC)内で実行されます。
| コンポーネント | 仕様 | 台数 |
|---|---|---|
| PolarDB-X 1.0(Starter Edition) | 8 コア 32 GB | 1 |
| PolarDB-X 1.0(Standard Edition) | 16 コア 64 GB | 1 |
| PolarDB-X 1.0(Enterprise Edition) | 32 コア 128 GB | 1 |
| PolarDB-X 1.0(Enterprise Edition) | 64 コア 256 GB | 1 |
| ECS ストレストテスト用マシン | 32 コア 64 GB、Alibaba Cloud Linux 2.1903 64 ビット、エンハンストコンピューティングネットワーク対応 | 1 |
| ApsaraDB RDS for MySQL(専用、MySQL 5.7) | 16 コア 64 GB | 12 |
テスト環境の構築
上記の表に記載された仕様に基づき、PolarDB-X 1.0 インスタンス(各仕様 1 台ずつ、計 4 台)、Elastic Compute Service(ECS)インスタンス 1 台、および ApsaraDB RDS for MySQL インスタンス 12 台を購入します。
PolarDB-X 1.0 コンソールで、水平分割(シャーディング)によりデータベースシャードを作成し、購入済みの 12 台の ApsaraDB RDS for MySQL インスタンスを選択します。
ECS インスタンスに Sysbench をインストールし、1 億 6,000 万行のテストデータを準備します。インストール手順については、「Sysbench ユーザーガイド」をご参照ください。
テストパラメーターの構成
以下の共通パラメーターを設定ファイル(例: sysbench.config)に保存し、両シナリオで再利用できるようにします。
# データ構成
--oltp-table-size=160000000
--oltp_auto_inc=off
--oltp_secondary
--oltp_range_size=5
--rand-init=on
# 接続構成
--mysql-user=<your-username>
--mysql-password=<your-password>
--mysql-host=<your-host>
--mysql-port=3306
--mysql-db=<your-database>
--mysql-table-engine=innodb
# シャーディング構成(PolarDB-X 1.0 構文:データベースシャードあたりテーブルシャード 2 つ)
--mysql_table_options='dbpartition by hash(`id`) tbpartition by hash(id) tbpartitions 2'OLTP シナリオと SELECT シナリオでは、使用する Lua スクリプトおよび並行スレッド数が異なります。
| パラメーター | OLTP シナリオ | SELECT シナリオ |
|---|---|---|
--test | /usr/local/share/sysbench/oltp_drds.lua | /usr/local/share/sysbench/select.lua |
--oltp_skip_trx | on | on |
--num-threads | インスタンスエディションに応じて変動(結果表を参照) | インスタンスエディションに応じて変動(結果表を参照) |
テストの実行
sysbench.config に定義したパラメーターに、シナリオ固有の引数を追加してテストを実行します。以下の例では、200 の並行スレッドで OLTP テストを 300 秒間実行します。
sysbench \
--test='/usr/local/share/sysbench/oltp_drds.lua' \
--oltp_tables_count=1 \
--oltp-table-size=160000000 \
--oltp_auto_inc=off \
--oltp_skip_trx=on \
--oltp_secondary \
--oltp_range_size=5 \
--mysql_table_options='dbpartition by hash(`id`) tbpartition by hash(id) tbpartitions 2' \
--mysql-user=<your-username> \
--mysql-password=<your-password> \
--mysql-host=<your-host> \
--mysql-port=3306 \
--mysql-db=<your-database> \
--mysql-table-engine=innodb \
--rand-init=on \
--num-threads=200 \
--report-interval=5 \
--max-requests=0 \
--max-time=300 \
runプレースホルダーを実際の値に置き換えてください。
| プレースホルダー | 説明 |
|---|---|
<your-username> | データベースユーザー名 |
<your-password> | データベースパスワード |
<your-host> | PolarDB-X 1.0 エンドポイント |
<your-database> | 対象データベース名 |
OLTP テスト結果
| インスタンス仕様 | 並行スレッド数 | 1 秒あたりの読み取り/書き込み操作数 |
|---|---|---|
| 8 コア 32 GB(Starter Edition) | 100 | 20,807.12 |
| 16 コア 64 GB(Standard Edition) | 230 | 49,667.48 |
| 32 コア 128 GB(Enterprise Edition) | 450 | 90,693.70 |
| 64 コア 256 GB(Enterprise Edition) | 900 | 177,506.48 |
SELECT テスト結果
| インスタンス仕様 | 並行スレッド数 | 1 秒あたりの読み取り/書き込み操作数 |
|---|---|---|
| 8 コア 32 GB(Starter Edition) | 200 | 41,401.00 |
| 16 コア 64 GB(Standard Edition) | 300 | 98,182.26 |
| 32 コア 128 GB(Enterprise Edition) | 600 | 180,500.00 |
| 64 コア 256 GB(Enterprise Edition) | 1,200 | 366,863.48 |
Sysbench の合成ベンチマークは、制御された条件下でのスループットを測定します。実際の本番環境におけるパフォーマンスは、ご利用のクエリパターン、データ分散、ワークロード特性に依存します。
OLTP シナリオ用テストスクリプト
これらのテストで使用される oltp_drds.lua スクリプトを以下に示します(参考用)。
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function get_range_end(start)
return start + oltp_range_size - 1
end
function thread_init(thread_id)
set_vars()
if (((db_driver == "mysql") or (db_driver == "attachsql")) and mysql_table_engine == "myisam") then
local i
local tables = {}
for i=1, oltp_tables_count do
tables[i] = string.format("sbtest%i WRITE", i)
end
begin_query = "LOCK TABLES " .. table.concat(tables, " ,")
commit_query = "UNLOCK TABLES"
else
begin_query = "BEGIN"
commit_query = "COMMIT"
end
end
function event(thread_id)
local rs
local i
local table_name
local range_start
local c_val
local pad_val
local query
table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count)
if not oltp_skip_trx then
db_query(begin_query)
end
if not oltp_write_only then
for i=1, oltp_point_selects do
rs = db_query("SELECT c FROM ".. table_name .." WHERE id=" .. sb_rand(1, oltp_table_size))
end
if oltp_range_selects then
for i=1, oltp_simple_ranges do
range_start = sb_rand(1, oltp_table_size)
rs = db_query("SELECT c FROM ".. table_name .." WHERE id BETWEEN " .. range_start .. " AND " .. get_range_end(range_start))
end
for i=1, oltp_sum_ranges do
range_start = sb_rand(1, oltp_table_size)
rs = db_query("SELECT SUM(K) FROM ".. table_name .." WHERE id BETWEEN " .. range_start .. " AND " .. get_range_end(range_start))
end
for i=1, oltp_order_ranges do
range_start = sb_rand(1, oltp_table_size)
rs = db_query("SELECT c FROM ".. table_name .." WHERE id BETWEEN " .. range_start .. " AND " .. get_range_end(range_start) .. " ORDER BY c")
end
for i=1, oltp_distinct_ranges do
range_start = sb_rand(1, oltp_table_size)
rs = db_query("SELECT DISTINCT c FROM ".. table_name .." WHERE id BETWEEN " .. range_start .. " AND " .. get_range_end(range_start) .. " ORDER BY c")
end
end
end
if not oltp_read_only then
for i=1, oltp_index_updates do
rs = db_query("UPDATE " .. table_name .. " SET k=k+1 WHERE id=" .. sb_rand(1, oltp_table_size))
end
for i=1, oltp_non_index_updates do
c_val = sb_rand_str("###########-###########-###########-###########-###########-###########-###########-###########-###########-###########")
query = "UPDATE " .. table_name .. " SET c='" .. c_val .. "' WHERE id=" .. sb_rand(1, oltp_table_size)
rs = db_query(query)
if rs then
print(query)
end
end
for i=1, oltp_delete_inserts do
i = sb_rand(1, oltp_table_size)
rs = db_query("DELETE FROM " .. table_name .. " WHERE id=" .. i)
c_val = sb_rand_str([[
###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]])
pad_val = sb_rand_str([[
###########-###########-###########-###########-###########]])
rs = db_query("INSERT INTO " .. table_name .. " (id, k, c, pad) VALUES " .. string.format("(%d, %d, '%s', '%s')",i, sb_rand(1, oltp_table_size) , c_val, pad_val))
end
end -- oltp_read_only
if not oltp_skip_trx then
db_query(commit_query)
end
end