发表于 2025-1-22 19:56:31

BenchmarkSQL-5.0测试Postgre数据库

参考文章benchmarksql 测试Postgres-CSDN博客,由于原文中缺少对具体文件的配置,所以加以增补。
1.BenchmarkSQL介绍

BenchmarkSQL是一个开源数据库测试工具,内嵌了TPCC测试脚本,可以对EnterpriseDB、PostgreSQL、MySQL、Oracle以及SQL Server等多种数据库直接进行测试。
BenchmarkSQL的测试场景:
TPC-C(Transaction Processing Performance Council-C)是一个用于评估在线事件处理(OLTP)系统性能的基准测试标准,模拟了一个贸易订单处理系统。它包罗五种重要事件类型:新订单、支付、订单状态查询、库存状态查询和交货。TPC-C 测试评估数据库在处理高并发事件时的吞吐量(tpmC)、响应时间和扩展性,广泛用于数据库性能评测、硬件和软件选择及系统调优。
TPC-C 会模拟一个批发商的货品管理环境。该批发公司有N个仓库,每个仓库供应10个地区,
其中每个地区为3000 名顾客服务。在每个仓库中有10 个终端,每个终端用于一个地区。
在运行的时间,10*N 个终端操纵员会向公司的数据库发送5类请求。由于一个仓库中不可能
存储公司中所有的货品,有一些请求必须发往其他的仓库,因此数据库在逻辑上是分布的。
N 是一个可变的参数值,测试则可以将 N 作为传入参数。
2.BenchmarkSQL测试所需环境

利用 BenchmarkSQL 需要以下环境:

[*]Java JDK:通常需要 JDK 7 或更高版本。
[*]PostgreSQL 数据库(或其他支持的数据库,如 MySQL、Oracle):需要安装并配置数据库。
[*]JDBC 驱动:根据所利用的数据库,BenchmarkSQL 需要相应的 JDBC 驱动(例如 PostgreSQL、MySQL 等)。
[*]配置文件:需要根据目的数据库配置 BenchmarkSQL 的配置文件,确保数据库连接正常。
[*]ant:Ant是Java的生成工具,是Apache的核心项目;需要在安装好JDK后安装。
[*]R:需要安装R来生成最后的报告。
[*]benchmarksql-5.0下载地址:https://sourceforge.net/projects/benchmarksql/?source=typ_redirect,该项目利用java编写。
3.如何运行BenchmarkSQL(Windows系统)

在下载好的zip文件里,包含有一个HOW-TO-RUN,我们按照这个来运行。
(1)创建benchmarksql用户和数据库

利用SQL shell
CREATE USER benchmarksql WITH ENCRYPTED PASSWORD '123123';
CREATE DATABASE benchmarksql OWNER benchmarksql; (2)编译 BenchmarkSQL 源代码

在BenchmarkSQL源代码目录中包含有一个build文件,利用 ant 来编译:
cd benchmarksql
ant
这会生成须要的 JAR 文件 (BenchmarkSQL-5.0.jar),另有一个build文件夹包含了生成的各种类,后面需要配置这个路径。
(3)创建配置文件

切换到run文件夹,在这里需要配置一些东西,我们测试的事Postgre数据库,所以只需要修改props.pg即可,可以在bash中利用vim功能进行编辑,也可以直接在记事本中编辑。
cd run
cp props.pg my_postgres.properties
vi my_postgres.properties
在这个文件里需要修改一下连接,用户另有暗码,确保连接我们的测试数据库。
db=postgres
driver=org.postgresql.Driver
conn=jdbc:postgresql://localhost:5432/benchmarksql
user=benchmarksql
password=123123 注意: 提供的 props.pg 配置仅用于功能测试。如果要进行基准测试,可以根据需要调整系统配置参数(如数据库巨细、并发连接数等),在后边我们会跑两次测试,一次是基于事件数的测试,另有一次是基于时间的测试。
(4)创建数据库模式和加载初始数据

利用 runDatabaseBuild.sh 脚本来创建数据库模式并加载初始数据:
./runDatabaseBuild.sh my_postgres.properties
在这里会出现疯狂报错,大部分会提示无法加载主类ExecJDBC大概是LoadData,这里是由于在第二步编译的class类会默认放在build文件夹中,而runDatabaseBuild.sh会调用runSQL.sh和runLoader.sh。问题就出在后两个文件里边,由于在路径中不含有包含类的文件夹,所以需要我们自己来配置。
下边直接放上修改后的文件,文件里实在也会提示,如setmyCP大概利用exit 1这种来进行留白。
runSQL.sh
#!/usr/bin/env bash

# ----
# Check command line usage
# ----
if [ $# -ne 2 ] ; then
    echo "usage: $(basename $0) PROPS_FILE SQL_FILE" >&2
    exit 2
fi

# ----
# Load common functions
# ----
source funcs.sh $1

# ----
# Determine which SQL file to use.
#
# 1) If $2 specifies a file that ends in .sql, we use that.
# 2) If a file ./sql.<dbtype>/$2.sql exists, we use that.
# 3) If none of the above, use ./sql.common/$2.sql.
# ----
if echo "$2" | grep -q -e '\.sql$' ; then
    ENDS_WITH_SQL=1
else
    ENDS_WITH_SQL=0
fi

if [ -f "${2}" -a $ENDS_WITH_SQL -eq 1 ] ; then
    SQL_FILE="$2"
else
    if [ -f "./sql.$(getProp db)/${2}.sql" ] ; then
      SQL_FILE="./sql.$(getProp db)/${2}.sql"
    else
            SQL_FILE="./sql.common/${2}.sql"
        if [ ! -f "${SQL_FILE}" ] ; then
           echo "ERROR: Cannot locate SQL file for ${2}" >&2
           exit 1
        fi
    fi
fi

# ----
# Set myCP according to the database type.
# ----
myCP="D:/360MoveData/Users/HUAWEI/Desktop/benchmarksql-5.0/build;D:/360MoveData/Users/HUAWEI/Desktop/benchmarksql-5.0/lib/postgres/postgresql-9.3-1102.jdbc41.jar"



echo "# ------------------------------------------------------------"
echo "# Loading SQL file ${SQL_FILE}"
echo "# ------------------------------------------------------------"
myOPTS="-Dprop=$1"
myOPTS="$myOPTS -DcommandFile=${SQL_FILE}"
java -cp "$myCP" $myOPTS ExecJDBC
runLoader.sh
#!/usr/bin/env bash

if [ $# -lt 1 ] ; then
    echo "usage: $(basename $0) PROPS_FILE " >&2
    exit 2
fi

source funcs.sh $1
shift

# 手动设置类路径
myCP="D:/360MoveData/Users/HUAWEI/Desktop/benchmarksql-5.0/build;D:/360MoveData/Users/HUAWEI/Desktop/benchmarksql-5.0/lib/postgres/postgresql-9.3-1102.jdbc41.jar"



# 如果 funcs.sh 中有设置类路径的函数,可以保留它
# setCP || exit 1

java -cp "$myCP" -Dprop=$PROPS LoadData $*
这里实在就是设置了myCP,我这里利用的是绝对路径确保程序可以找到文件,实在这里加了两条路径(根据我的文件存储位置),分别是D:/360MoveData/Users/HUAWEI/Desktop/benchmarksql-5.0/build和D:/360MoveData/Users/HUAWEI/Desktop/benchmarksql-5.0/lib/postgres/postgresql-9.3-1102.jdbc41.jar,那么前一个路径用来解决类无法加载的问题,后边的路径设计别的一条报错,即无法调用jdbc,所以在这里把benchmarksql自带的jar文件附加到myCP中,确保可以正常调用。
改完之后可以实行运行一下runDatabaseBuild.sh ,这里可能还是会出现报错,缘故原由还是上边两个,于是我又重写了runDatabaseBuild.sh 文件,给这个文件也加上路径。
runDatabaseBuild.sh
#!/bin/sh

if [ $# -lt 1 ] ; then
    echo "usage: $(basename $0) PROPS ]" >&2
    exit 2
fi

PROPS="$1"
shift
if [ ! -f "${PROPS}" ] ; then
    echo "${PROPS}: no such file or directory" >&2
    exit 1
fi
DB="$(grep '^db=' $PROPS | sed -e 's/^db=//')"

# 设置 PostgreSQL JDBC 驱动路径
POSTGRES_JDBC="D:/360MoveData/Users/HUAWEI/Desktop/benchmarksql-5.0/lib/postgres/postgresql-9.3-1102.jdbc41.jar"
BUILD_DIR="D:/360MoveData/Users/HUAWEI/Desktop/benchmarksql-5.0/build"

# 包含所有 SQL 文件的路径
BEFORE_LOAD="tableCreates"
AFTER_LOAD="indexCreates foreignKeys extraHistID buildFinish"

# 添加类路径
CLASSPATH="$BUILD_DIR;$POSTGRES_JDBC"

# 执行 SQL 加载步骤
for step in ${BEFORE_LOAD} ; do
    ./runSQL.sh "${PROPS}" $step
done

# 执行数据加载器脚本
java -cp "$CLASSPATH" -Dprop=$PROPS LoadData $*

# 执行后续的 SQL 步骤
for step in ${AFTER_LOAD} ; do
    ./runSQL.sh "${PROPS}" $step
done
如许三个文件改完,这一步就应该是可以正常运行了。在这一步中会在数据库中创建相应的表、数据和各种约束,方便下一步进行测试。可以利用navicat来进行查看。
https://i-blog.csdnimg.cn/direct/e3c34f117b3b43dd9838eba5ec322c19.png
(5)运行基准测试

到这一步终于是可以运行基准测试了,还是在run文件夹中。
./runBenchmark.sh my_postgres.properties
这里大概率会出现雷同的问题,即无法加载类另有jdbc。同时还会跳出一个新的问题,即无法调用log4j,这里需要先去下载这个文件,然后配置好环境,接下来把log4j的bin文件路径也附加到myCP中去(这里只加给runBenchmark.sh一个文件就行了)。下边是我的runBenchmark.sh,在myCP里边设置了三个路径。
runBenchmark.sh
#!/usr/bin/env bash

if [ $# -ne 1 ] ; then
    echo "usage: $(basename $0) PROPS_FILE" >&2
    exit 2
fi

SEQ_FILE="./.jTPCC_run_seq.dat"
if [ ! -f "${SEQ_FILE}" ] ; then
    echo "0" > "${SEQ_FILE}"
fi
SEQ=$(expr $(cat "${SEQ_FILE}") + 1) || exit 1
echo "${SEQ}" > "${SEQ_FILE}"

source funcs.sh $1

myCP="D:/360MoveData/Users/HUAWEI/Desktop/benchmarksql-5.0/build;D:/360MoveData/Users/HUAWEI/Desktop/benchmarksql-5.0/lib/postgres/postgresql-9.3-1102.jdbc41.jar;D:/360MoveData/Users/HUAWEI/Desktop/log4j-1.2.17/apache-log4j-1.2.17/log4j-1.2.17.jar"

myOPTS="-Dprop=$1 -DrunID=${SEQ}"

java -cp "$myCP" $myOPTS jTPCC
接下来这一步就可以正常运行了,运行效果大概是如许的:https://i-blog.csdnimg.cn/direct/cbaf615d118c4f7c8d03bb17d9f4f031.png
(6)调整基准测试配置

完成初次测试后,可以通过修改 props.pg 文件来扩大基准测试的规模(增长仓库数、终端数和持续时间等)。
要从基于事件数的测试切换到基于时间的测试,可以修改以下参数:
runTxnsPerTerminal=0 runMins=3 重复上一步的操纵,会完成又一次的测试,每次测试生成的数据会包含在my_result_测试时间如许的一个文件夹中。
(7)效果报告

基准测试完成后,可以利用 generateReport.sh 脚本生成报告:
./generateReport.sh my_result_directory 这里把directory改成具体的时间。该脚本会生成HTML报告,并包含基准测试效果的图表。
我们以上一步runTxnsPerTerminal=0 runMins=3,生成的效果为例,下图是生成的文件:
https://i-blog.csdnimg.cn/direct/06cd5d280de14a3790077d83c9b46e14.png
report里边是如许的:
https://i-blog.csdnimg.cn/direct/3fb0931baf934a7484396e50d3ba0482.pnghttps://i-blog.csdnimg.cn/direct/bccd5726c5464af191bf1de5147aa3cc.png
这里会发现下边还是少了一些东西,这里对应着系统的资源利用。
打开generateReport.sh发现调用的是misc中的os_collector_linux的文件,由于我用的是Windows系统,所以这个文件并不适用,也导致下边的数据另有图片无法正常生成。
这里我也写了一个os_collector_windows,但是这里边涉及要改的东西有点多,由于代码自己就比较“屎”所以就没有继续测试,改完这个还要把props.pg再改一下,仅供参考:
#props.pg
osCollectorScript=./misc/os_collector_windows.py
osCollectorInterval=1
//osCollectorSSHAddr=user@dbhost
osCollectorDevices=cpu memory #os_collector_windows
import psutil
import time
import csv
import sys
import os

# ----
# main
# ----
def main(argv):
    global deviceFDs
    global lastDeviceData

    # ----
    # 获取 runID 和采集间隔
    # ----
    runID = int(argv)
    interval = float(argv)

    # ----
    # 初始化系统信息收集和输出CSV表头
    # ----
    sysInfo = ['run', 'elapsed', ]
    sysInfo += initSystemUsage()
    print(",".join())

    # ----
    # 获取指定的设备,设备格式为 net_<devname> 或 blk_<devname>
    # ----
    devices = []
    deviceFDs = {}
    lastDeviceData = {}
    for dev in argv:
      if dev.startswith('blk_'):
            devices.append(dev)
      elif dev.startswith('net_'):
            devices.append(dev)
      else:
            raise Exception("unknown device type '" + dev + "'")

    # ----
    # 初始化每个设备的使用情况
    # ----
    for dev in devices:
      if dev.startswith('blk_'):
            devInfo = ['run', 'elapsed', 'device', ]
            devInfo += initBlockDevice(dev)
            print(",".join())
      elif dev.startswith('net_'):
            devInfo = ['run', 'elapsed', 'device', ]
            devInfo += initNetDevice(dev)
            print(",".join())

    # ----
    # 输出表头
    # ----
    sys.stdout.flush()

    try:
      while True:
            # ----
            # 等待下一个采集间隔,并计算经过的时间(毫秒)
            # ----
            now = time.time()
            elapsed = int((now - float(argv)) * 1000.0)

            # ----
            # 收集 CPU 和内存使用信息
            # ----
            sysInfo =
            sysInfo += getSystemUsage()
            print(",".join())

            # ----
            # 收集每个设备的使用情况
            # ----
            for dev in devices:
                if dev.startswith('blk_'):
                  devInfo =
                  devInfo += getBlockUsage(dev, interval)
                  print(",".join())
                elif dev.startswith('net_'):
                  devInfo =
                  devInfo += getNetUsage(dev, interval)
                  print(",".join())

            # ----
            # 更新下一次采集的时间
            # ----
            time.sleep(interval)

            sys.stdout.flush()

    except KeyboardInterrupt:
      print("")
      return 0

    except IOError as e:
      if e.errno == errno.EPIPE:
            return 0
      else:
            raise e

def initSystemUsage():
    return ['cpu_percent', 'memory_percent']

def getSystemUsage():
    # 获取 CPU 和内存使用率
    cpu_percent = psutil.cpu_percent(interval=1)
    memory_percent = psutil.virtual_memory().percent

    return

def initBlockDevice(dev):
    # Windows 没有类似 Linux 的 /sys/block 路径,因此需要使用 psutil 获取磁盘 I/O 信息
    return ['rdiops', 'rdkbps', 'wriops', 'wrkbps']

def getBlockUsage(dev, interval):
    # 使用 psutil 获取磁盘 I/O 数据
    disk_io = psutil.disk_io_counters()
    rdiops = disk_io.read_count
    wriops = disk_io.write_count
    rd_bytes = disk_io.read_bytes
    wr_bytes = disk_io.write_bytes

    # 计算每秒的读写次数和数据量
    return

def initNetDevice(dev):
    # 获取网络接口的初始数据
    return ['rxpktsps', 'rxkbps', 'txpktsps', 'txkbps']

def getNetUsage(dev, interval):
    # 获取网络接口的流量数据
    net_io = psutil.net_io_counters()
    rx_pkts = net_io.bytes_recv
    tx_pkts = net_io.bytes_sent

    # 计算每秒的接收和发送流量
    return [
      rx_pkts / interval,
      rx_pkts / interval / 1024.0,
      tx_pkts / interval,
      tx_pkts / interval / 1024.0
    ]

if __name__ == '__main__':
    sys.exit(main(sys.argv))
4.报告内容分析

最后来看看报告里边写了什么,我这份报告是以时间为基准测试的(3分钟)。
https://i-blog.csdnimg.cn/direct/deae1f742c0c4fada18236f94e54d35f.png
 (1)整体性能:



[*] Overall tpmC: 124.67
[*] Overall tpmTotal: 280.67
[*] tpmC 是核心事件(NEW_ORDER)每分钟处理的事件数。
[*] tpmTotal 是所有类型的事件(包罗NEW_ORDER、Payment、Order Status、Delivery和Stock Level)每分钟的总事件数。
这里的tpmC为124.67,意味着每分钟大约处理124.67个NEW_ORDER事件,这是TPC-C基准测试中最为关键的性能指标。
(2)理论最大值:



[*]理论最大值:12.86 NEW_ORDER 事件/分钟/仓库
TPC-C规范指出,在理想的条件下,每个仓库的NEW_ORDER事件理论最大值为12.86。要到达这个最大值,需要:


[*]完善的负载分配(45%的事件是NEW_ORDER)。
[*]系统在零响应时间下运行。
现实上,由于系统的延迟和负载不平衡,很难到达这个理论最大值。
   (3)现实性能 vs 理论性能:



[*]124.67 tpmC 是理论最大值的 969.414%
这意味着系统的现实性能是理论最大值的约9.7倍。也就是说,相较于理想状态,当前的系统性能远超预期,表明该数据库配置在特定负载下的表现非常好。思量到系统的现实响应时间和负载,这种超出理论最大值的表现通常表明系统在某些方面(如硬件配置、数据库优化、并行处理等)非常高效。
(4)生成的两张图:

https://i-blog.csdnimg.cn/direct/2d3157af7500443783021b15a7489202.png
每分钟事件数量。
https://i-blog.csdnimg.cn/direct/a8835af03b1449d9a00dc0aea5dd8fdd.png
事件延迟。
说点题外话:
跑这个测试从十月就开始搞,由于中间有考试另有大作业,一直也没有什么进展,而且中间一直报错也是相称的烦人,终于在十二月初算上搞通了。相称于是成功复现了一篇论文,纵然是最新的benchmarksql也是2016年的版本了,而且说实话也并不好用,各种东西都需要改才能跑的动,当然要让我写一个数据库测试工具,估计也得到猴年马月了,接下来还是要继续努力。
                                                                                                                         记于2024年12月7日

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: BenchmarkSQL-5.0测试Postgre数据库