TPC 是事务处理性能委员会组织,该委员会致力于制定和维护一系列标准化的基准测试,以评估商业计算系统的性能。其中最著名的是一系列用于评估计算机系统性能的基准测试。
以下是TPC组织使用的一些标准:
除了这些基准测试之外,TPC组织还制定了一些其他标准,用于规范化基准测试的执行和报告,以确保测试的公正性、可重复性和可比性。
官网传送门:TPC-C 官网
说明书获取传送门:TPC Current Specs
TPC-C标准测试模拟了五种不同类型的事务处理【原文70页】。这些事务处理分别是:
TPC-C标准中规定的各类事务响应时间【原文72页】:
响应时间是指终端响应的时间(确认事务已排队),而不是事务本身的执行时间。至少90%的事务必须在排队后的80秒内完成(参见第2.7.2.2条款)。
目前常用的开源TPC-C基准测试工具有mysql-tpcc 、 HammerDB 、Benchmarksql 等。
但这些开源TPC-C基准测试工具中,目前没有专门支持SQLite数据库的...
以下图示展示了TPC-C业务环境中的仓库 warehouse、销售区域 district 和客户的层次结构。
官网原文: The company portrayed by the benchmark is a wholesale supplier with a number of geographically distributed sales districts and associated warehouses. As the company's business expands, new warehouses and associated sales districts are created. Each regional warehouse covers 10 districts. Each district serves 3,000 customers. All warehouses maintain stocks for the 100,000 items sold by the company. The following diagram illustrates the warehouse, district, and customer hierarchy of TPC-C's business environment.
解释:
基准测试中描述的公司 company 是一家批发供应商,具有多个地理分布的销售区域 district 和关联仓库 warehouse。随着公司业务的扩展,将创建新的仓库和相应的销售区域。每个区域性仓库 warehouses 覆盖 10 个销售区域 district,每个销售区域 district 为 3k 名客户提供服务。所有仓库 warehouses 都储备公司销售的10万种商品。
官网原文: The components of the TPC-C database are defined to consist of nine separate and individual tables. The relationships among these tables are defined in the entity-relationship diagram shown below and are subject to the rules specified in Clause 1.4.
解释:
TPC-C数据库的组件被定义为由九个单独且独立的表组成。这些表之间的关系在下面显示的实体-关系图中定义,并受到第1.4条规定的规则的约束。
说明: 图中9个实体对应了TPC-C测试中9个数据表,也对应批发模型中参与的对象。Warehouse是仓库,District是区域,每个Warehouse为10个区域提供商品批发,Customer是客户,每个区域有3千个客户,每个客户会产生至少1个订单,每个订单又分为New-Order和Order-line两部分,New-Order是用来标示订单是否为新订单,在完成订单的发货操作后,New-Order中的记录将被删除,Order-line是订单中进行批发的商品订购流水,每个订单有5到10个交易商品。Stock是用来记录Warehouse的库存情况,Item是记录Warehouse中所存储的商品。 其中:
官方说明:
五种事务涉及所对应的表: New-Order:新订单,主要对应 new_orders 表 Payment:支付,主要对应 orders、history 表 Order-Status:订单状态,主要对应 orders、order_line 表 Delivery:发货,主要对应 order_line 表 Stock-Level:库存,主要对应 stock 表 其他: 客户:主要对应 customer 表 地区:主要对应 district 表 商品:主要对应 item 表 仓库:主要对应 warehouse 表
以下列表定义了每个表的最小结构(属性列表),其中:
备注如下:
对于 warehouse table:
对于 district table:
对于 customer table:
对于 history table:
对于 new_order table:
对于 order table:
对于 order_line table:
对于 item table:
对于 stock table:
PRAGMA foreign_keys=off;
drop table if exists warehouse;
create table warehouse (
w_id smallint not null,
w_name varchar(10),
w_street_1 varchar(20),
w_street_2 varchar(20),
w_city varchar(20),
w_state char(2),
w_zip char(9),
w_tax decimal(4,2),
w_ytd decimal(12,2),
primary key (w_id) );
drop table if exists district;
create table district (
d_id tinyint not null,
d_w_id smallint not null,
d_name varchar(10),
d_street_1 varchar(20),
d_street_2 varchar(20),
d_city varchar(20),
d_state char(2),
d_zip char(9),
d_tax decimal(4,2),
d_ytd decimal(12,2),
d_next_o_id int,
primary key (d_w_id, d_id) );
drop table if exists customer;
create table customer (
c_id int not null,
c_d_id tinyint not null,
c_w_id smallint not null,
c_first varchar(16),
c_middle char(2),
c_last varchar(16),
c_street_1 varchar(20),
c_street_2 varchar(20),
c_city varchar(20),
c_state char(2),
c_zip char(9),
c_phone char(16),
c_since datetime,
c_credit char(2),
c_credit_lim bigint,
c_discount decimal(4,2),
c_balance decimal(12,2),
c_ytd_payment decimal(12,2),
c_payment_cnt smallint,
c_delivery_cnt smallint,
c_data text,
PRIMARY KEY(c_w_id, c_d_id, c_id) );
drop table if exists history;
create table history (
h_c_id int,
h_c_d_id tinyint,
h_c_w_id smallint,
h_d_id tinyint,
h_w_id smallint,
h_date datetime,
h_amount decimal(6,2),
h_data varchar(24) );
drop table if exists new_orders;
create table new_orders (
no_o_id int not null,
no_d_id tinyint not null,
no_w_id smallint not null,
PRIMARY KEY(no_w_id, no_d_id, no_o_id));
drop table if exists orders;
create table orders (
o_id int not null,
o_d_id tinyint not null,
o_w_id smallint not null,
o_c_id int,
o_entry_d datetime,
o_carrier_id tinyint,
o_ol_cnt tinyint,
o_all_local tinyint,
PRIMARY KEY(o_w_id, o_d_id, o_id) );
drop table if exists order_line;
create table order_line (
ol_o_id int not null,
ol_d_id tinyint not null,
ol_w_id smallint not null,
ol_number tinyint not null,
ol_i_id int,
ol_supply_w_id smallint,
ol_delivery_d datetime,
ol_quantity tinyint,
ol_amount decimal(6,2),
ol_dist_info char(24),
PRIMARY KEY(ol_w_id, ol_d_id, ol_o_id, ol_number) );
drop table if exists item;
create table item (
i_id int not null,
i_im_id int,
i_name varchar(24),
i_price decimal(5,2),
i_data varchar(50),
PRIMARY KEY(i_id) );
drop table if exists stock;
create table stock (
s_i_id int not null,
s_w_id smallint not null,
s_quantity smallint,
s_dist_01 char(24),
s_dist_02 char(24),
s_dist_03 char(24),
s_dist_04 char(24),
s_dist_05 char(24),
s_dist_06 char(24),
s_dist_07 char(24),
s_dist_08 char(24),
s_dist_09 char(24),
s_dist_10 char(24),
s_ytd decimal(8,0),
s_order_cnt smallint,
s_remote_cnt smallint,
s_data varchar(50),
PRIMARY KEY(s_w_id, s_i_id) );
PRAGMA foreign_keys=on;
这里我使用了 PRAGMA foreign_keys=off;
来关闭外键检查,然后在操作结束后使用 PRAGMA foreign_keys=on;
来重新打开外键检查。
PRAGMA foreign_keys=off;
-- 创建索引
CREATE INDEX idx_customer ON customer (c_w_id,c_d_id,c_last,c_first);
CREATE INDEX idx_orders ON orders (o_w_id,o_d_id,o_c_id,o_id);
CREATE INDEX fkey_stock_2 ON stock (s_i_id);
CREATE INDEX fkey_order_line_2 ON order_line (ol_supply_w_id,ol_i_id);
-- 外键约束
ALTER TABLE district ADD CONSTRAINT fkey_district_1 FOREIGN KEY(d_w_id) REFERENCES warehouse(w_id);
ALTER TABLE customer ADD CONSTRAINT fkey_customer_1 FOREIGN KEY(c_w_id,c_d_id) REFERENCES district(d_w_id,d_id);
ALTER TABLE history ADD CONSTRAINT fkey_history_1 FOREIGN KEY(h_c_w_id,h_c_d_id,h_c_id) REFERENCES customer(c_w_id,c_d_id,c_id);
ALTER TABLE history ADD CONSTRAINT fkey_history_2 FOREIGN KEY(h_w_id,h_d_id) REFERENCES district(d_w_id,d_id);
ALTER TABLE new_orders ADD CONSTRAINT fkey_new_orders_1 FOREIGN KEY(no_w_id,no_d_id,no_o_id) REFERENCES orders(o_w_id,o_d_id,o_id);
ALTER TABLE orders ADD CONSTRAINT fkey_orders_1 FOREIGN KEY(o_w_id,o_d_id,o_c_id) REFERENCES customer(c_w_id,c_d_id,c_id);
ALTER TABLE order_line ADD CONSTRAINT fkey_order_line_1 FOREIGN KEY(ol_w_id,ol_d_id,ol_o_id) REFERENCES orders(o_w_id,o_d_id,o_id);
ALTER TABLE order_line ADD CONSTRAINT fkey_order_line_2 FOREIGN KEY(ol_supply_w_id,ol_i_id) REFERENCES stock(s_w_id,s_i_id);
ALTER TABLE stock ADD CONSTRAINT fkey_stock_1 FOREIGN KEY(s_w_id) REFERENCES warehouse(w_id);
ALTER TABLE stock ADD CONSTRAINT fkey_stock_2 FOREIGN KEY(s_i_id) REFERENCES item(i_id);
PRAGMA foreign_keys=on;
PRAGMA foreign_keys=off;
-- 删除外键约束
ALTER TABLE district DROP CONSTRAINT fkey_district_1;
ALTER TABLE customer DROP CONSTRAINT fkey_customer_1;
ALTER TABLE history DROP CONSTRAINT fkey_history_1;
ALTER TABLE history DROP CONSTRAINT fkey_history_2;
ALTER TABLE new_orders DROP CONSTRAINT fkey_new_orders_1;
ALTER TABLE orders DROP CONSTRAINT fkey_orders_1;
ALTER TABLE order_line DROP CONSTRAINT fkey_order_line_1;
ALTER TABLE order_line DROP CONSTRAINT fkey_order_line_2;
ALTER TABLE stock DROP CONSTRAINT fkey_stock_1;
ALTER TABLE stock DROP CONSTRAINT fkey_stock_2;
PRAGMA foreign_keys=on;
TPCC-MySQL 是指使用 MySQL 数据库系统进行 TPC-C 基准测试的实现,TPCC-MySQL 则是在 MySQL 数据库上实现的 TPC-C 基准测试的版本。
虽然这是针对 mysql 进行测试,但我们可以用来参考。
官网地址:GitHub上 - Percona-Lab/tpcc-mysql 实验环境:阿里云轻量应用服务器
项目结构介绍
在操作之前需要安装mysql和mysql编译时链接的库
sudo apt-get update
sudo apt-get install mysql-server mysql-client libmysqlclient-dev
# 启动 mysql 服务器
sudo service mysql start
按照下面进行后续操作
# 服务器拉取源码
git clone https://github.com/Percona-Lab/tpcc-mysql.git
# 进入工作目录并编译
cd tpcc-mysql/src && make
编译完成后会在./tpcc-mysql 目录下生成两个可执行文件 tpcc_load、tpcc_start
1. 创建数据库tpcc1000【在./tpcc-mysql目录操作】
mysqladmin create tpcc1000
# 上面语句不行就使用下面这条
# mysqladmin -u root -p -S /var/run/mysqld/mysqld.sock create tpcc1000
查看名为 tcpp1000 的mysql数据库是否创建成功:
mysql -u root -p -S /var/run/mysqld/mysqld.sock -e "SHOW DATABASES;"
2. 创建表
mysql tpcc1000 < create_table.sql
显示 tcpp1000 数据库内部的表:
mysql -uroot -p -e "show tables from tpcc1000"
红框内就是创建的9张表:
3. 创建相关索引和主外键(此步骤可在加载数据后完成)
mysql tpcc1000 < add_fkey_idx.sql
4.填充数据(4.1、4.2任选一种)
真实测试场景中,仓库数一般不建议少于100个,视服务器硬件配置而定,如果是配备了SSD或者PCIE SSD这种高IOPS设备的话,建议最少不低于1000个。仓库越多,造数据的时间越长,需要耐心等待.
4.1 单进程加载数据,记得将 your_root_password 改成自己的密码【官网建了1000个仓库,太慢了我只建了10个,控制最后一个 -w 的参数】
下面的官网指令无论怎么改都会报错,建议直接看“补充”内容往下走。
./tpcc_load -h 127.0.0.1 -d tpcc1000 -u root -p "your_root_password" -w 10
# |hostname:port| |dbname| |user| |password| |仓库|
补充:
如果加载数据遇到下面内容:
解决方法:新建一个用户tpcc,密码设置成tpcc去执行这个指令
# 1.登录MySQL服务器:使用具有足够权限的用户(例如root用户)登录MySQL服务器
mysql -u root -p
# 2.创建新用户tpcc,密码为tpcc
CREATE USER 'tpcc'@'%' IDENTIFIED BY 'tpcc';
# 说明:这个命令创建了一个名为tpcc的用户,可以从任何主机(%)连接,密码为tpcc。如果希望只允许从特定主机连接,可以将'%'替换为特定的主机名或IP地址
# 3.授予权限:为tpcc用户授予适当的权限,这里授予其在tpcc1000数据库上的全部权限
GRANT ALL PRIVILEGES ON tpcc1000.* TO 'tpcc'@'%';
# 4.刷新权限,以使新授权生效。
FLUSH PRIVILEGES;
# 5.退出MySQL命令行界面
exit;
现在再次执行:
./tpcc_load -h 127.0.0.1 -d tpcc1000 -u tpcc -p "tpcc" -w 10
下面就开始加载数据了:
指令会创建10个 warsehouse,加载完成后显示如下:
造数据成功后,会提示:…DATA LOADING COMPLETED SUCCESSFULLY.
另外可以使用下面指令查看帮助:
./tpcc_load --help
4.2 并发加载数据【选择了4.1 就跳过这一步 】
选择a:官网原始的并发加载文件【使用 load.sh 并发加载数据,亲测无效,该项目太久没维护了(2016年之前的老项目了)】,这里选择并发加载10个warsehouse
./load.sh tpcc1000 10
造数据成功后,会提示:…DATA LOADING COMPLETED SUCCESSFULLY.
选择b:GitHub上另一个并行加载脚本: https://gist.github.com/sh2/3458844
根据实际情况情况修改用户名、密码、数据库名,初始仓库为10个。
在tpcc_mysql 路径下创建sh文件:
vim tpcc_load_parallel.sh
由于最新版本tpcc_load使用方法需要显示使用参数,修改脚本内容参考如下:
#!/bin/bash
# Configration
MYSQL=/usr/bin/mysql
TPCCLOAD=./tpcc_load
TABLESQL=./create_table.sql
CONSTRAINTSQL=./add_fkey_idx.sql
DEGREE=`getconf _NPROCESSORS_ONLN`
SERVER=localhost
DATABASE=tpcc
USER=tpcc
PASS=tpcc
WAREHOUSE=10
# Load
set -e
$MYSQL -u $USER -p$PASS -e "DROP DATABASE IF EXISTS $DATABASE"
$MYSQL -u $USER -p$PASS -e "CREATE DATABASE $DATABASE"
$MYSQL -u $USER -p$PASS $DATABASE < $TABLESQL
$MYSQL -u $USER -p$PASS $DATABASE < $CONSTRAINTSQL
echo 'Loading item ...'
$TPCCLOAD -h $SERVER -d $DATABASE -u $USER -p $PASS -w $WAREHOUSE 1 1 -n $WAREHOUSE > /dev/null
set +e
STATUS=0
trap 'STATUS=1; kill 0' INT TERM
for ((WID = 1; WID <= WAREHOUSE; WID++)); do
echo "Loading warehouse id $WID ..."
(
set -e
# warehouse, stock, district
$TPCCLOAD -h $SERVER -d $DATABASE -u $USER -p $PASS -w $WAREHOUSE 2 -m $WID -n $WID > /dev/null
# customer, history
$TPCCLOAD -h $SERVER -d $DATABASE -u $USER -p $PASS -w $WAREHOUSE 3 -m $WID -n $WID > /dev/null
# orders, new_orders, order_line
$TPCCLOAD -h $SERVER -d $DATABASE -u $USER -p $PASS -w $WAREHOUSE 4 -m $WID -n $WID > /dev/null
) &
PIDLIST=(${PIDLIST[@]} $!)
if [ $((WID % DEGREE)) -eq 0 ]; then
for PID in ${PIDLIST[@]}; do
wait $PID
if [ $? -ne 0 ]; then
STATUS=1
fi
done
if [ $STATUS -ne 0 ]; then
exit $STATUS
fi
PIDLIST=()
fi
done
for PID in ${PIDLIST[@]}; do
wait $PID
if [ $? -ne 0 ]; then
STATUS=1
fi
done
if [ $STATUS -eq 0 ]; then
echo 'Completed.'
fi
exit $STATUS
后续执行即可。
tpcc_start工具用于tpcc压测,基础测试指令也要根据自己建立的内容进行修改,比如仓库-w建了10个,那么这里-w后面就接10
# 开始基准测试
./tpcc_start -h 127.0.0.1 -P 3306 -d tpcc1000 -u tpcc -p "tpcc" -w 10 -c 32 -r 10 -l 20
# |主机名| |端口| |dbname| |用户| |仓库| |连接| |预热时间| |基准时间|
示例参数说明:
# 指令模板
./tpcc_start -h 127.0.0.1 -P3306 -dtpcc1000 -uroot -p "your_password" -w100 -c10 -r100 -l300 -i20
***************************************
*** ###easy### TPC-C Load Generator ***
***************************************
option h with value '127.0.0.1'
option p with value '3306'
option d with value 'tpcc1000' //创建的数据库名
option u with value 'root' //创建的用户
option p with value 'your_password' //自己的密码
option w with value '100' //仓库数,必须和tpcc_load一致
option c with value '10' //连接数,可认为是线程数
option r with value '10' //预热时间,以秒为单位,默认10秒,主要是为了将数据加载到内存;
option l with value '300' //测试执行时间,以秒为单位,默认是20秒;
option i with value '20' //产生报告的时间间隔,默认是10秒
<Parameters>
[server]: 127.0.0.1
[port]: 3306
[DBname]: tpcc1000
[user]: root
[pass]: 123123 [warehouse]: 10
[connection]: 10
[rampup]: 100 (sec.)
[measure]: 300 (sec.)
使用定义的间隔(-i 选项),该工具将生成以下输出:
10, trx: 12920, 95%: 9.483, 99%: 18.738, max_rt: 213.169, 12919|98.778, 1292|101.096, 1293|443.955, 1293|670.842
20, trx: 12666, 95%: 7.074, 99%: 15.578, max_rt: 53.733, 12668|50.420, 1267|35.846, 1266|58.292, 1267|37.421
30, trx: 13269, 95%: 6.806, 99%: 13.126, max_rt: 41.425, 13267|27.968, 1327|32.242, 1327|40.529, 1327|29.580
40, trx: 12721, 95%: 7.265, 99%: 15.223, max_rt: 60.368, 12721|42.837, 1271|34.567, 1272|64.284, 1272|22.947
50, trx: 12573, 95%: 7.185, 99%: 14.624, max_rt: 48.607, 12573|45.345, 1258|41.104, 1258|54.022, 1257|26.626
解释如下:
按照 4.2 的tpcc压测会弹出下面内容:
图中的第一部分就是 章节4.2.c 的参数说明。 图中的第二部分就是 章节4.3.a 的官网说明。
图中的第三部分说明:汇总了各种业务各状态的数据量
<Raw Results>
[0] sc:0 lt:1052 rt:0 fl:0 avg_rt: 440.4 (5)
[1] sc:0 lt:1053 rt:0 fl:0 avg_rt: 193.7 (5)
[2] sc:8 lt:97 rt:0 fl:0 avg_rt: 71.0 (5)
[3] sc:0 lt:104 rt:0 fl:0 avg_rt: 1270.6 (80)
[4] sc:0 lt:104 rt:0 fl:0 avg_rt: 1477.3 (20)
in 20 sec.
<Raw Results2(sum ver.)>
[0] sc:0 lt:1052 rt:0 fl:0
[1] sc:0 lt:1053 rt:0 fl:0
[2] sc:8 lt:97 rt:0 fl:0
[3] sc:0 lt:104 rt:0 fl:0
[4] sc:0 lt:104 rt:0 fl:0
这段内容提供了对TPC-C基准测试的原始结果进行了分析。分析如下:
Raw Results:
Raw Results2 (sum ver.): 这部分提供了原始结果的汇总版本,将所有并发线程的统计信息总结在一起。每个条目表示所有并发线程的总和。这些总和与Raw Results中的详细统计信息对应。 这些结果显示了每种事务类型的性能指标,包括提交计数、事务数量、失败数量和平均响应时间。
第四部分:
<Constraint Check> (all must be [OK])
[transaction percentage]
Payment: 43.55% (>=43.0%) [OK]
Order-Status: 4.34% (>= 4.0%) [OK]
Delivery: 4.30% (>= 4.0%) [OK]
Stock-Level: 4.30% (>= 4.0%) [OK]
[response time (at least 90% passed)]
New-Order: 0.00% [NG] *
Payment: 0.00% [NG] *
Order-Status: 7.62% [NG] *
Delivery: 0.00% [NG] *
Stock-Level: 0.00% [NG] *
<TpmC>
3156.000 TpmC
这段内容提供了对TPC-C基准测试的约束检查和TPM-C(Transactions Per Minute - C)指标的分析,分析如下:
约束检查 (Constraint Check):
TPM-C (Transactions Per Minute - C):
综上,约束检查部分提供了对每种事务类型的性能和负载情况的分析,而TPM-C指标则提供了整体性能的度量。