使用 HammerDB 对 SQL Server 执行负载测试


本教程介绍了如何使用 HammerDB 在 Compute Engine SQL Server 实例上执行负载测试。您可以通过学习以下教程来了解如何安装 SQL Server 实例:

有多种负载测试工具可供使用。其中一些是免费的开源工具,而另一些则需要许可。HammerDB 是一种开源工具,通常很适合演示 SQL Server 数据库的性能。本教程介绍了使用 HammerDB 的基本步骤,不过,您也可以使用其他工具,但应该选择最适合特定工作负载的工具。

目标

本教程介绍了以下目标:

  • 配置 SQL Server 以进行负载测试
  • 安装并运行 HammerDB
  • 收集运行时统计信息
  • 运行源自 TPC“C”规范 (TPROC-C) 的负载测试的事务处理基准

费用

除了在 Compute Engine 上运行的任何现有 SQL Server 实例外,本教程还使用了 Google Cloud 的收费组件,包括:

  • Compute Engine
  • Windows Server

您可以使用价格计算器根据您的预计使用情况来估算费用。点击提供的链接即可查看本教程中使用的产品的估算费用(平均每天 16 美元)。Google Cloud 新用户可能有资格申请免费试用

准备工作

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  5. Make sure that billing is enabled for your Google Cloud project.

  6. 如果您在本地机器上使用的不是 Windows,请安装第三方远程桌面协议 (RDP) 客户端。如需了解详情,请参阅 Microsoft 远程桌面客户端

配置 SQL Server 实例以进行负载测试

在开始之前,您应该仔细检查 Windows 防火墙规则是否设置为允许来自您创建的新 Windows 实例的 IP 地址的流量。然后,请您按照以下步骤创建一个新数据库以进行 TPCC 负载测试,并配置一个用户账号:

  1. 右键点击 SQL Server Management Studio 中的数据库文件夹,然后选择新建数据库
  2. 将新的数据库命名为“TPCC”。
  3. 将数据文件的初始大小设置为 190000 MB,并将日志文件大小设置为 65000 MB。
  4. 点击省略号按钮,将自动增长限制的值调高,如以下屏幕截图所示:

    设置自动增长限制

  5. 将数据文件大小上限设置为无限制(文件每次增大 64 MB)。

  6. 将日志文件设置为停用自动增长。

  7. 点击确定

  8. 新建数据库对话框的左侧窗格中,选择选项页面。

  9. Compatibility level 设置为 SQL Server 2022 (160)

  10. 恢复模型设置为简单,以防止负载填满事务日志。

    将恢复模型设置为“简单”

  11. 点击确定以创建 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 Console 中,转到创建实例页面。

    转到“创建实例”

  2. 对于名称,输入 hammerdb-instance

  3. 机器配置部分中,选择具有至少一半 CPU 数量的机器类型作为您的数据库实例。

  4. 启动磁盘部分,点击更改,然后执行以下操作:

    1. 公共映像标签页上,选择 Windows Server 操作系统。
    2. 版本列表中,点击 Windows Server 2022 Datacenter
    3. 启动磁盘类型列表中,选择标准永久性磁盘
    4. 如需确认您的启动磁盘选项,请点击选择
  5. 要创建并启动该虚拟机,请点击创建

安装软件

准备就绪后,使用 RDP 客户端连接到新的 Windows Server 实例并安装以下软件:

运行 HammerDB

安装 HammerDB 后,运行 hammerdb.bat 文件。HammberDB 不会在“开始”菜单的应用列表中显示。可使用以下命令运行 HammerDB:

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

VERSION 替换为已安装的 HammerDB 的版本。

创建连接和架构

应用运行后,您首先要配置连接来构建架构。

  1. 基准面板中,双击 SQL Server
  2. 选择 TPROC-C。在 HammerDB 网站中:
    TPROC-C 是在 HammerDB 中实现的 OLTP 工作负载,源自 TPROC-C 规范,并经过修改,以便在任何受支持的数据库环境中运行 HammerDB 时都能够简单高效。HammerDB TPROC-C 工作负载是源自 TPROC-C 基准标准的开源工作负载,因此无法与已发布的 TPROC-C 结果进行比较,因为这些结果符合部分而非完整的 TPROC-C 基准标准。HammerDB 工作负载 TPROC-C 的名称表示“源自 TPC“C”规范的事务处理基准”。
  3. 点击确定

    设置 TPROC-C 基准选项

  4. 点击 Schema,然后双击 Options

  5. 使用您的 IP 地址、用户名和密码填写表单,如下图所示:

    设置 TPROC-C 构建选项

  6. SQL Server ODBC Driver 设置为 OBDC Driver 18 for SQL Server

  7. 在这种情况下,将 Number of Warehouses(规模)设置为 460,但您可以选择其他值。部分准则建议为每个 CPU 创建 10 到 100 个仓库。 在本教程中,您可将此值设置为核心数量的 10 倍:对于 16 核的实例,可将此值设置为 160。

  8. 对于构建架构的虚拟用户数,请选择一个介于客户端 vCPU 数量 1 到 2 倍之间的数字。如需增大该数字,请点击滑块旁边的灰色条。

  9. 清除 Use BPC Option

  10. 点击确定

  11. 双击 Schema Build 部分下方的 Build 选项以创建架构并加载表。此操作完成后,点击屏幕顶部中心的红色闪光灯图标以销毁虚拟用户,然后转到下一步。

如果您使用 Simple 恢复模型创建数据库,则可能需要在此时将模式更改回 Full,以获得更准确的生产场景测试结果。请注意,只有您执行完整备份或差分备份以触发新日志链启动后,此操作才会生效。

创建驱动程序脚本

HammerDB 使用驱动程序脚本将 SQL 语句流调控至数据库,以生成所需的负载。

  1. 基准面板中,展开驱动程序脚本部分,然后双击选项
  2. 验证设置是否与您在架构构建对话框中使用的设置一致。
  3. 选择 Timed Driver Script
  4. 完成时的检查点选项会强制数据库在测试结束时将所有内容写入磁盘,因此请仅在计划连续运行多个测试时,才选中此选项。
  5. 为确保测试完整而全面,请将预热启动时间的分钟数设置为 5,将测试持续时间的分钟数设置为 20。
  6. 点击确定以退出对话框。
  7. 基准面板的驱动程序脚本部分,双击加载以激活驱动程序脚本。

设置 TPROC-C 驱动程序选项

创建虚拟用户

要创建真实的负载,通常需要您以多个不同的用户身份来运行脚本。因此,请为测试创建若干虚拟用户。

  1. 展开虚拟用户部分,然后双击选项
  2. 如果您将仓库数量(规模)设置为 160,则将 Virtual Users 设置为 16,因为 TPROC-C 准则建议采用 10 倍比例以防止行锁定。选择显示输出复选框后,错误消息将能够显示在控制台中。
  3. 点击确定

收集运行时统计信息

HammerDB 和 SQL Server 无法轻松为您收集详细的运行时统计信息。虽然统计信息可在 SQL Server 的深层获取,但您需要定期捕获这些信息并进行计算。如果您没有可捕获此数据的过程或工具,请使用以下过程在测试期间收集一些有用的指标。结果将写入 Windows temp 目录中的 CSV 文件。您可以使用选择性粘贴 > 粘贴 CSV 选项将数据复制到 Google 表格中。

如需使用此过程,您首先必须临时启用 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. 基准面板的虚拟用户下方,双击创建以创建虚拟用户,这将激活虚拟用户输出标签。
  2. 双击创建选项正下方的运行以启动测试。
  3. 测试完成后,您将在虚拟用户输出标签页中看到计算得出的每分钟处理的事务数 (TPM) 结果。
  4. 您可以在 c:\Windows\temp 目录中找到您的收集过程的结果。
  5. 将所有这些值保存到 Google 表格中,然后使用它们来比较多个测试运行项。

清理

完成本教程后,您可以清理您创建的资源,让它们停止使用配额,以免产生费用。以下部分介绍如何删除或关闭这些资源。

删除项目

为了避免产生费用,最简单的方法是删除您为本教程创建的项目。

如需删除项目,请执行以下操作:

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

删除实例

如需删除 Compute Engine 实例,请执行以下操作:

  1. In the Google Cloud console, go to the VM instances page.

    Go to VM instances

  2. Select the checkbox for the instance that you want to delete.
  3. To delete the instance, click More actions, click Delete, and then follow the instructions.

后续步骤