HammerDB を使用した SQL Server の負荷テスト

このチュートリアルでは、HammerDB を使用して Compute Engine の SQL Server インスタンスに負荷テストを実施する方法を説明します。SQL Server インスタンスをインストールする方法については、次のチュートリアルで学習できます。

利用可能な負荷テストツールは複数あります。一部はフリーのオープンソースですが、その他はライセンスが必要です。HammerDB はオープンソース ツールですが、一般的に SQL Server データベースのパフォーマンスを実証するために適切に機能します。このチュートリアルでは、HammerDB を使用するための基本的な手順に対応していますが、他にも利用可能なツールがあります。使用する特定のワークロードに最適なツールを選択してください。

SQL Server インスタンスを負荷テスト用に構成する

開始する前に、Windows ファイアウォール ルールが、作成された新しい Windows インスタンスの IP アドレスからのトラフィックを許可するように設定されていることを、再確認してください。次に、TPCC 負荷テスト用の新しいデータベースを作成し、次の手順を使用してユーザー アカウントを構成します。

  1. SQL Server Management Studio で [データベース] フォルダを右クリックし、[新しいデータベース] を選択します。
  2. 新しいデータベースに「TPCC」という名前を付けます。
  3. データファイルの初期サイズを 190,000 MB に、またログファイルの初期サイズを 65,000 MB に設定します。
  4. 次のスクリーンショットに示す省略記号ボタンをクリックして、[自動拡張] の制限値をより高い値に設定します。

    自動拡張の上限の設定

  5. データファイルを、64 MB ずつ無制限のサイズまで拡張されるように設定します。

  6. ログファイルの自動拡張を無効に設定します。

  7. [OK] をクリックします。

  8. [新しいデータベース] ダイアログで、左側のペインから [オプション] ページを選択します。

  9. [互換性レベル] を [SQL Server 2022 (160)] に設定します。

  10. [復旧モデル] を [単純] に設定し、負荷によってトランザクション ログがいっぱいにならないようにします。

    復旧モデルを [シンプル] に設定

  11. [OK] をクリックして、TPCC データベースを作成します。これには数分かかることがあります。

  12. 事前構成された SQL Server イメージは、Windows 認証が有効な場合にのみ表示されます。そのため、こちらのガイドに沿って、SSMS 内で混合モード認証を有効にする必要があります。

  13. こちらの手順で DBOwner 権限がある SQL Server のユーザー アカウントを、データベース上に作成します。アカウントに「loaduser」という名前を付け、安全なパスワードを設定します。

  14. Get-NetIPAddress コマンドレットを使用して SQL Server の内部 IP アドレスをメモしておきます。内部 IP の使用は、パフォーマンスとセキュリティの面で重要だからです。

HammerDB のインストール

SQL Server インスタンス上で直接 HammerDB を実行することができますが、より正確にテストするため、新しい Windows インスタンスを作成してリモートで SQL Server インスタンスをテストします。

インスタンスの作成

次の手順で新規の Compute Engine インスタンスを作成します。

  1. Google Cloud コンソールで [インスタンスの作成] ページに移動します。

    [インスタンスの作成] に移動

  2. [名前] に「hammerdb-instance」と入力します。

  3. [マシンの構成] セクションで、データベース インスタンスとして半数以上の CPU があるマシンタイプを選択します。

  4. [ブートディスク] セクションで [変更] をクリックし、次の操作を行います。

    1. [公開イメージ] タブで、Windows Server オペレーティング システムを選択します。
    2. [バージョン] リストで、[Windows Server 2022 Datacenter] をクリックします。
    3. [ブートディスクの種類] プルダウン リストで、[標準永続ディスク] を選択します。
    4. ブートディスクのオプションを確認するには、[選択] をクリックします。
  5. VM を作成して起動するには、[作成] をクリックします。

ソフトウェアのインストール

準備ができたら、RDP クライアントを使用して新しい Windows Server インスタンスに接続し、次のソフトウェアをインストールします。

HammerDB の実行

HammerDB をインストールしたら、hammerdb.bat ファイルを実行します。HammberDB は、[スタート] メニューのアプリケーション リストに表示されません。次のコマンドを実行して、HammerDB を実行します。

C:\Program Files\HammerDB-VERSION\hammerdb.bat

VERSION は、インストールされている HammerDB のバージョンに置き換えます。

接続とスキーマの作成

アプリケーションが実行されたら、最初のステップは、スキーマを構築するための接続を設定することです。

  1. [Benchmark] パネルで [SQL Server] をダブルクリックします。
  2. [TPROC-C] を選択します。HammerDB サイトからの引用:
    TPROC-C は、HammerDB に実装されている OLTP ワークロードです。TPC-C 仕様から派生したものであり、サポートされているデータベース環境で HammerDB を簡単かつ費用対効果の高い方法で実行できるように変更が加えられています。HammerDB TPROC-C ワークロードは、TPC-C ベンチマーク標準から派生したオープンソースのワークロードです。したがって、結果は TPC-C の完全なベンチマーク標準ではなくサブセットに準拠しているため、公開されている TPC-C の結果と比較することはできません。HammerDB ワークロード TPROC-C の名前は、「TPC 「C」仕様から派生したトランザクション処理ベンチマーク」を意味します。
  3. [OK] をクリックします。

    TPROC-C ベンチマーク オプションの設定

  4. [Schema] をクリックし、[Options] をダブルクリックします。

  5. 次の図に示すように、IP アドレス、ユーザー名、パスワードを使用してフォームに入力します。

    TPROC-C ビルド オプションの設定

  6. [SQL Server ODBC Driver] を ODBC Driver 18 for SQL Server に設定します。

  7. この場合、[Number of Warehouses](規模)は 460 に設定されますが、別の値を選択することもできます。一部のガイドラインでは、ウェアハウスの数を 1 CPU あたり 10~100 にすることを推奨しています。 このチュートリアルでは、この値をコア数の 10 倍に設定します。16 コアのインスタンスでは 160 です。

  8. [Virtual Users to Build Schema] には、クライアント vCPU 数の 1~2 倍の値を選択します。スライダーの隣にある灰色のバーをクリックすると、数値を変更できます。

  9. [Use BPC Option] をオフにします。

  10. [OK] をクリックします。

  11. [Schema Build] セクションの下にある [Build] オプションをダブルクリックして、スキーマを作成し、テーブルを読み込みます。完了したら、画面の上部中央にある赤色灯のアイコンをクリックして仮想ユーザーを破棄し、次の手順に進みます。

Simple の復旧モデルでデータベースを作成した場合、本番環境シナリオをより正確にテストできるように、この時点で Full に戻す必要が生じることもあります。この変更は、フル バックアップまたは差分バックアップを取って新しいログチェーンの開始をトリガーするまで有効になりません。

ドライバ スクリプトの作成

HammerDB はドライバ スクリプトを使用してデータベースに対する SQL ステートメントのフローをオーケストレートし、必要な負荷を生成します。

  1. [Benchmark] パネルで、[Driver Script] セクションを展開して [Options] をダブルクリックします。
  2. 設定が、[Schema Build] ダイアログで使用したものと一致することを確認してください。
  3. [Timed Driver Script] を選択します。
  4. [Checkpoint when complete] オプションをオンにすると、テスト終了時にデータベースの内容がすべてディスクに書き込まれます。そのため、複数のテストを連続して行う場合にのみオンにします。
  5. テストを確実に完遂するため、[Minutes of Rampup Time] を 5 に、[Minutes for Test Duration] を 20 に設定します。
  6. [OK] をクリックして、ダイアログを終了します。
  7. [Benchmark] パネルの [Driver Script] セクションで、[Load] をダブルクリックしてドライバ スクリプトをアクティブにします。

TPROC-C ドライバ オプションの設定

仮想ユーザーの作成

一般に、現実的な負荷を作成するには、複数の異なるユーザーとしてスクリプトを実行する必要があります。そのため、テスト用に仮想ユーザーをいくつか作成します。

  1. [Virtual Users] セクションを開いて [Options] をダブルクリックします。
  2. ウェアハウス数(規模)を 160 に設定した場合は、[Virtual Users] を 16 に設定します。これは TPROC-C のガイドラインが、行のロックを防止するために 10 倍の比率を推奨していることによります。[Show Output] チェックボックスをオンにしてコンソールのエラー メッセージを有効にします。
  3. [OK] をクリックします。

ランタイム統計情報の収集

HammerDB および SQL Server では、詳細なランタイム統計情報は、簡単には収集されません。統計情報は、SQL Server 内部にありますが、捕捉して定期的に計算する必要があります。このデータをキャプチャするために役立つ手順やツールがまだない場合は、このセクションの手順を利用して、テストの間にいくつかの有用な指標をキャプチャできます。結果は、Windows の temp ディレクトリで CSV ファイルに書き込まれます。データを Google スプレッドシートに、[特殊貼り付け] > [Paste CSV] オプションを使用してコピーできます。

この手順を使用するには、OLE 自動プロシージャを一時的に有効にして、ファイルをディスクに書き込みます。テスト後に無効にすることを忘れないでください。

sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO

以下は、SQL Server Management Studio で sp_write_performance_counters プロシージャを作成するコードです。負荷テスト開始前に、Management Studio でこの手順を実施してください。

USE [master]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

/***
LogFile path has to be in a directory that SQL Server can Write To.
*/
CREATE PROCEDURE [dbo].[sp_write_performance_counters] @LogFile varchar (2000) = 'C:\\WINDOWS\\TEMP\\sqlPerf.log', @SecondsToRun int =1600, @RunIntervalSeconds int = 2

AS

BEGIN
--File writing variables
DECLARE @OACreate INT, @OAFile INT, @FileName VARCHAR(2000), @RowText VARCHAR(500), @Loops int, @LoopCounter int, @WaitForSeconds varchar (10)
--Variables to save last counter values
DECLARE @LastTPS BIGINT, @LastLRS BIGINT, @LastLTS BIGINT, @LastLWS BIGINT, @LastNDS BIGINT, @LastAWT BIGINT, @LastAWT_Base BIGINT, @LastALWT BIGINT, @LastALWT_Base BIGINT
--Variables to save current counter values
DECLARE @TPS BIGINT, @Active BIGINT, @SCM BIGINT, @LRS BIGINT, @LTS BIGINT, @LWS BIGINT, @NDS BIGINT, @AWT BIGINT, @AWT_Base BIGINT, @ALWT BIGINT, @ALWT_Base BIGINT, @ALWT_DIV BIGINT, @AWT_DIV BIGINT

SELECT @Loops = case when (@SecondsToRun % @RunIntervalSeconds) > 5 then @SecondsToRun / @RunIntervalSeconds + 1 else @SecondsToRun / @RunIntervalSeconds end
SET @LoopCounter = 0
SELECT @WaitForSeconds = CONVERT(varchar, DATEADD(s, @RunIntervalSeconds , 0), 114)
SELECT @FileName = @LogFile + FORMAT ( GETDATE(), '-MM-dd-yyyy_m', 'en-US' ) + '.txt'

--Create the File Handler and Open the File
EXECUTE sp_OACreate 'Scripting.FileSystemObject', @OACreate OUT
EXECUTE sp_OAMethod @OACreate, 'OpenTextFile', @OAFile OUT, @FileName, 2, True, -2

--Write the Header
EXECUTE sp_OAMethod @OAFile, 'WriteLine', NULL,'Transactions/sec, Active Transactions, SQL Cache Memory (KB), Lock Requests/sec, Lock Timeouts/sec, Lock Waits/sec, Number of Deadlocks/sec, Average Wait Time (ms), Average Latch Wait Time (ms)'
--Collect Initial Sample Values
SET ANSI_WARNINGS OFF
SELECT
  @LastTPS= max(case when counter_name = 'Transactions/sec' then cntr_value end),
  @LastLRS = max(case when counter_name = 'Lock Requests/sec' then cntr_value end),
  @LastLTS = max(case when counter_name = 'Lock Timeouts/sec' then cntr_value end),
  @LastLWS = max(case when counter_name = 'Lock Waits/sec' then cntr_value end),
  @LastNDS = max(case when counter_name = 'Number of Deadlocks/sec' then cntr_value end),
  @LastAWT = max(case when counter_name = 'Average Wait Time (ms)' then cntr_value end),
  @LastAWT_Base = max(case when counter_name = 'Average Wait Time base' then cntr_value end),
  @LastALWT = max(case when counter_name = 'Average Latch Wait Time (ms)' then cntr_value end),
  @LastALWT_Base = max(case when counter_name = 'Average Latch Wait Time base' then cntr_value end)
FROM sys.dm_os_performance_counters
WHERE counter_name IN (
'Transactions/sec',
'Lock Requests/sec',
'Lock Timeouts/sec',
'Lock Waits/sec',
'Number of Deadlocks/sec',
'Average Wait Time (ms)',
'Average Wait Time base',
'Average Latch Wait Time (ms)',
'Average Latch Wait Time base') AND instance_name IN( '_Total' ,'')
SET ANSI_WARNINGS ON
WHILE @LoopCounter <= @Loops
BEGIN
WAITFOR DELAY @WaitForSeconds
SET ANSI_WARNINGS OFF
SELECT
  @TPS= max(case when counter_name = 'Transactions/sec' then cntr_value end)   ,
  @Active = max(case when counter_name = 'Active Transactions' then cntr_value end)   ,
  @SCM = max(case when counter_name = 'SQL Cache Memory (KB)' then cntr_value end)   ,
  @LRS = max(case when counter_name = 'Lock Requests/sec' then cntr_value end)   ,
  @LTS = max(case when counter_name = 'Lock Timeouts/sec' then cntr_value end)   ,
  @LWS = max(case when counter_name = 'Lock Waits/sec' then cntr_value end)   ,
  @NDS = max(case when counter_name = 'Number of Deadlocks/sec' then cntr_value end)   ,
  @AWT = max(case when counter_name = 'Average Wait Time (ms)' then cntr_value end)   ,
  @AWT_Base = max(case when counter_name = 'Average Wait Time base' then cntr_value end)   ,
  @ALWT = max(case when counter_name = 'Average Latch Wait Time (ms)' then cntr_value end)   ,
  @ALWT_Base = max(case when counter_name = 'Average Latch Wait Time base' then cntr_value end)
FROM sys.dm_os_performance_counters
WHERE counter_name IN (
'Transactions/sec',
'Active Transactions',
'SQL Cache Memory (KB)',
'Lock Requests/sec',
'Lock Timeouts/sec',
'Lock Waits/sec',
'Number of Deadlocks/sec',
'Average Wait Time (ms)',
'Average Wait Time base',
'Average Latch Wait Time (ms)',
'Average Latch Wait Time base') AND instance_name IN( '_Total' ,'')
SET ANSI_WARNINGS ON

SELECT  @AWT_DIV = case when (@AWT_Base - @LastAWT_Base) > 0 then (@AWT_Base - @LastAWT_Base) else 1 end ,
    @ALWT_DIV = case when (@ALWT_Base - @LastALWT_Base) > 0 then (@ALWT_Base - @LastALWT_Base) else 1 end

SELECT @RowText = '' + convert(varchar, (@TPS - @LastTPS)/@RunIntervalSeconds) + ', ' +
          convert(varchar, @Active) + ', ' +
          convert(varchar, @SCM) + ', ' +
          convert(varchar, (@LRS - @LastLRS)/@RunIntervalSeconds) + ', ' +
          convert(varchar, (@LTS - @LastLTS)/@RunIntervalSeconds) + ', ' +
          convert(varchar, (@LWS - @LastLWS)/@RunIntervalSeconds) + ', ' +
          convert(varchar, (@NDS - @LastNDS)/@RunIntervalSeconds) + ', ' +
          convert(varchar, (@AWT - @LastAWT)/@AWT_DIV) + ', ' +
          convert(varchar, (@ALWT - @LastALWT)/@ALWT_DIV)

SELECT  @LastTPS = @TPS,
    @LastLRS = @LRS,
    @LastLTS = @LTS,
    @LastLWS = @LWS,
    @LastNDS = @NDS,
    @LastAWT = @AWT,
    @LastAWT_Base = @AWT_Base,
    @LastALWT = @ALWT,
    @LastALWT_Base = @ALWT_Base

EXECUTE sp_OAMethod @OAFile, 'WriteLine', Null, @RowText

SET @LoopCounter = @LoopCounter + 1

END

--CLEAN UP
EXECUTE sp_OADestroy @OAFile
EXECUTE sp_OADestroy @OACreate
print 'Completed Logging Performance Metrics to file: ' + @FileName

END

GO

TPROC-C 負荷テストの実行

SQL Server Management Studio で、次のスクリプトを使用してコレクション手順を実施します。

Use master
Go
exec dbo.sp_write_performance_counters

HammerDB をインストールした Compute Engine インスタンスで、HammerDB アプリケーションのテストを開始します。

  1. [Benchmark] パネルの [Virtual Users] で、[Create] をダブルクリックして仮想ユーザーを作成します。これにより、[Virtual User Output] タブがアクティブになります。
  2. [Create] のすぐ下にある [Run] をダブルクリックして、テストを開始します。
  3. テストが完了すると、[Virtual User Output] タブに 1 分あたりのトランザクション数(TPM)の計算値が表示されます。
  4. コレクション手順の結果は、c:\Windows\temp ディレクトリにあります。
  5. これらの値をすべて Google スプレッドシートに保存し、複数のテストの比較に使用します。