§ TPC-H性能测试
本文主要介绍采用 TPC-H 工具对 GreatSQL 进行性能测试的方法。
§ 关于TPC-H
TPC-H是TPC(Transaction Processing Performance Council)组织提供的工具包。主要用于进行OLAP业务场景测试,以评估商业分析中决策支持系统(DSS)的性能。它包含了一整套面向商业的ad-hoc查询和并发数据修改,强调测试的是数据库、平台和I/O性能,关注查询能力。
官网:http://www.tpc.org/tpch (opens new window)
§ 编译安装TPC-H
1. 下载TPC-H
访问TPC-H下载页面 (opens new window),下载源码包。
2. 下载完后,解压缩,并复制 makefile.suite 文件
$ unzip 41aa248b-48a5-11ee-8bef-d08e7908bcb1-tpc-h-tool.zip
$ cd TPC-H_Tools_v3.0.1
$ cd dbgen
$ cp makefile.suite Makefile
 2
3
4
3. 修改Makefile以适配
$ vim Makefile
CC      = gcc
# Current values for DATABASE are: INFORMIX, DB2, TDAT (Teradata)
#                                  SQLSERVER, SYBASE, ORACLE, VECTORWISE
# Current values for MACHINE are:  ATT, DOS, HP, IBM, ICL, MVS,
#                                  SGI, SUN, U2200, VMS, LINUX, WIN32
# Current values for WORKLOAD are:  TPCH
DATABASE= MYSQL
MACHINE = LINUX
WORKLOAD = TPCH
 2
3
4
5
6
7
8
9
10
4. 修改tpcd.h文件,在文件末尾新增几行MYSQL宏定义
$ vim tpcd.h
#ifdef MYSQL
#define GEN_QUERY_PLAN ""
#define START_TRAN "START TRANSACTION"
#define END_TRAN "COMMIT"
#define SET_OUTPUT ""
#define SET_ROWCOUNT "limit %d;\n"
#define SET_DBASE "use %s;\n"
#endif
 2
3
4
5
6
7
8
9
5. 编译
执行make编译,编译完毕后会生成两个可执行文件:
- dbgen:数据生成工具。在使用InfiniDB官方测试脚本进行测试时,需要用该工具生成tpch相关表数据。
 - qgen:SQL生成工具
 
§ 生成测试数据
可根据实际情况,生成 1、10、100、1000 等不同数据集比例因子(Scale Factor)级别的测试数据,例如 30:
$ ./dbgen -vf -s 30
 最后会生成数个 .tbl 文件:
$ ls -lh
-rw-r--r-- 1 root root 703M Jul 19 15:36 customer.tbl
-rw-r--r-- 1 root root  23G Jul 19 15:36 lineitem.tbl
-rw-r--r-- 1 root root 2.2K Jul 19 15:36 nation.tbl
-rw-r--r-- 1 root root 5.0G Jul 19 15:36 orders.tbl
-rw-r--r-- 1 root root 3.4G Jul 19 15:36 partsupp.tbl
-rw-r--r-- 1 root root 699M Jul 19 15:36 part.tbl
-rw-r--r-- 1 root root  389 Jul 19 15:36 region.tbl
-rw-r--r-- 1 root root  41M Jul 19 15:36 supplier.tbl
 2
3
4
5
6
7
8
9
还可以利用 pdbgen.sh脚本 (opens new window) 来生成测试数据集,它采用并行的方法,每个大表生成多个文件切片,其效率相比直接调用 dbgen 至少可以提升一倍。这种多文件切片的方式,也更有利于后续采用 pload.sh脚本 (opens new window)) 实现更高效并发导入。
§ 生成TPC-H测试查询SQL
可直接访问gitee仓库获取相应的SQL (opens new window),这些 SQL 脚本文件可直接用于测试 GreatSQL 的 Rapid 引擎,已经加上了相应的 HINT,例如:
-- tpch_queries_1.sql
SELECT /*+ SET_VAR(use_secondary_engine=1) SET_VAR(secondary_engine_cost_threshold=0) */ /*+ Q1 */
    l_returnflag,
    l_linestatus,
...
 2
3
4
5
也可参考下面的方法手动生成22个TPC-H测试查询SQL:
# 生成22个SQL文件
$ for i in $(seq 1 22); do ./qgen -d $i -s 1000 > tpch_queries_"$i".sql; done
# 转换文件格式
$ dos2unix *.sql
 2
3
4
5
参数 -s 1000 表示测试数据集比例因子是 1000,不同比例因子的区别在于第 11 个查询SQL中的条件因子,在 tpch_queries_11.sql 中也已注明:
-- cat tpch_queries_11.sql
...
        SELECT
            sum(ps_supplycost * ps_availqty) * 0.0001000000 /* SF1 */
            /* sum(ps_supplycost * ps_availqty) * 0.0000100000 /* SF10 */
            /* sum(ps_supplycost * ps_availqty) * 0.0000010000 /* SF100 */
            /* sum(ps_supplycost * ps_availqty) * 0.0000001000 /* SF1000 */
        FROM
...
 2
3
4
5
6
7
8
9
§ 新建TPC-H测试数据库,导入测试数据
§ 初始化TPC-H测试库表
- 下载 tpch-create-table.sql文件 (opens new window),导入数据库,完成TPC-H测试库表初始化。
 
文件内容如下:
-- DROP DATABASE IF EXISTS tpch;
-- CREATE DATABASE IF NOT EXISTS tpch DEFAULT CHARACTER SET latin1;
-- USE tpch;
drop table if exists nation;
create table nation  ( n_nationkey  bigint not null,
                n_name       char(25) not null,
                n_regionkey  bigint not null,
                n_comment    varchar(152),
                primary key(n_nationkey),
                key nation_fk1 (n_regionkey) ) secondary_engine = rapid;
drop table if exists region;
create table region  ( r_regionkey  bigint not null,
                r_name       char(25) not null,
                r_comment    varchar(152),
                primary key(r_regionkey) ) secondary_engine = rapid;
drop table if exists part;
create table part  ( p_partkey     bigint not null,
                p_name        varchar(55) not null,
                p_mfgr        char(25) not null,
                p_brand       char(10) not null,
                p_type        varchar(25) not null,
                p_size        integer not null,
                p_container   char(10) not null,
                p_retailprice decimal(15,2) not null,
                p_comment     varchar(23) not null,
                primary key(p_partkey) ) secondary_engine = rapid;
drop table if exists supplier;
create table supplier ( s_suppkey     bigint not null,
                s_name        char(25) not null,
                s_address     varchar(40) not null,
                s_nationkey   bigint not null,
                s_phone       char(15) not null,
                s_acctbal     decimal(15,2) not null,
                s_comment     varchar(101) not null,
                primary key(s_suppkey),
                key supplier_fk1 (s_nationkey) ) secondary_engine = rapid;
drop table if exists partsupp;
create table partsupp ( ps_partkey     bigint not null,
                ps_suppkey     bigint not null,
                ps_availqty    integer not null,
                ps_supplycost  decimal(15,2)  not null,
                ps_comment     varchar(199) not null,
                primary key(ps_partkey,ps_suppkey),
                key partsupp_fk1 (ps_suppkey),
                key partsupp_fk2 (ps_partkey) ) secondary_engine = rapid;
drop table if exists customer;
create table customer ( c_custkey     bigint not null,
                c_name        varchar(25) not null,
                c_address     varchar(40) not null,
                c_nationkey   bigint not null,
                c_phone       char(15) not null,
                c_acctbal     decimal(15,2)   not null,
                c_mktsegment  char(10) not null,
                c_comment     varchar(117) not null,
                primary key(c_custkey),
                key customer_fk1 (c_nationkey) ) secondary_engine = rapid;
drop table if exists orders;
create table orders  ( o_orderkey       bigint not null,
                o_custkey        bigint not null,
                o_orderstatus    char(1) not null,
                o_totalprice     decimal(15,2) not null,
                o_orderdate      date not null,
                o_orderpriority  char(15) not null,
                o_clerk          char(15) not null,
                o_shippriority   integer not null,
                o_comment        varchar(79) not null,
                primary key(o_orderkey),
                key orders_fk1 (o_custkey) ) secondary_engine = rapid;
drop table if exists lineitem;
create table lineitem ( l_orderkey    bigint not null,
                l_partkey     bigint not null,
                l_suppkey     bigint not null,
                l_linenumber  bigint not null,
                l_quantity    decimal(15,2) not null,
                l_extendedprice  decimal(15,2) not null,
                l_discount    decimal(15,2) not null,
                l_tax         decimal(15,2) not null,
                l_returnflag  char(1) not null,
                l_linestatus  char(1) not null,
                l_shipdate    date not null,
                l_commitdate  date not null,
                l_receiptdate date not null,
                l_shipinstruct char(25) not null,
                l_shipmode     char(10) not null,
                l_comment      varchar(44) not null,
                primary key(l_orderkey,l_linenumber),
                key lineitem_fk1 (l_orderkey) ,
                key lineitem_fk2 (l_partkey,l_suppkey) ) secondary_engine = rapid;
 2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
上述 SQL 脚本在建表时,同时指定了辅助引擎为 Rapid,便于后续进行 TPC-H 性能测试。
- 并行导入数据
 
可以利用GreatSQL提供的 并行 LOAD DATA 特性并行导入测试数据,提高导入效率:
$ mysql -f -e "load /*+ SET_VAR(gdb_parallel_load=ON) */ data infile '/data/tpch/region.tbl' into table region FIELDS TERMINATED BY '|'; analyze table region;" tpch
$ mysql -f -e "load /*+ SET_VAR(gdb_parallel_load=ON) */ data infile '/data/tpch/data/nation.tbl' into table nation FIELDS TERMINATED BY '|'; analyze table nation;" tpch
$ mysql -f -e "load /*+ SET_VAR(gdb_parallel_load=ON) */ data infile '/data/tpch/data/supplier.tbl' into table supplier FIELDS TERMINATED BY '|'; analyze table supplier;" tpch
$ mysql -f -e "load /*+ SET_VAR(gdb_parallel_load=ON) */ data infile '/data/tpch/data/part.tbl' into table part FIELDS TERMINATED BY '|'; analyze table part;" tpch
$ mysql -f -e "load /*+ SET_VAR(gdb_parallel_load=ON) */ data infile '/data/tpch/data/customer.tbl' into table customer FIELDS TERMINATED BY '|'; analyze table customer;" tpch
$ mysql -f -e "load /*+ SET_VAR(gdb_parallel_load=ON) */ data infile '/data/tpch/data/partsupp.tbl' into table partsupp FIELDS TERMINATED BY '|'; analyze table partsupp;" tpch
$ mysql -f -e "load /*+ SET_VAR(gdb_parallel_load=ON) */ data infile '/data/tpch/data/orders.tbl' into table orders FIELDS TERMINATED BY '|'; analyze table orders;" tpch
$ mysql -f -e "load /*+ SET_VAR(gdb_parallel_load=ON) */ data infile '/data/tpch/data/lineitem.tbl' into table lineitem FIELDS TERMINATED BY '|'; analyze table lineitem;" tpch
 2
3
4
5
6
7
8
9
10
11
12
13
14
15
还可以进一步设置并行 LOAD DATA 的并行线程数以及分片大小,详情参考文档:并行 LOAD DATA。
前面提到,可以使用 pdbgen.sh脚本 (opens new window) 生成(多文件多切片式的)测试数据集,因此可以相应地使用 pload.sh脚本 (opens new window) 在已经开启 并行LOAD DATA 的基础上,实现双重并行导入,其效率相对原生的 LOAD DATA 至少可提升数倍。
§ 开始TPC-H测试
在开始测试前,先调低 long_query_time 的值(甚至可以设置为0),使得可以记录所有TPC-H查询测试请求:
# 设置 long_query_time = 1ms
greatsql> set global long_query_time = 0.001;
# 甚至设置为 0,即记录所有请求
#greatsql> set global long_query_time = 0;
 2
3
4
5
在前面 4. 生成TPC-H测试查询SQL 中已经生成了测试22个测试查询SQL文件,逐一执行这些查询文件,也可以写个小脚本来执行,并分别记录运行耗时:
$ cat run-thch.sh
#!/bin/bash
workdir=/data/tpch
tpchdb="tpch"
host="172.16.16.10"
port="3306"
user="tpch"
passwd="tpch"
logdir="tpch-runlog-`date +%Y%m%d`"
sleeptime=5
cd ${workdir}
mkdir -p ${logdir}
MYSQL_CLI="mysql -h"${host}" -P"${port}" -u"${user}" -p"${passwd}" -f ${tpchdb}"
# 每个查询SQL执行5遍,其中前2遍是预热
for i in $(seq 1 22)
do
 for j in $(seq 1 5)
 do
   if [ ${j} -le 2 ] ; then
     time_1=`date +%s%N`
     $MYSQL_CLI < ./queries/tpch_queries_$i.sql > /dev/null 2>&1
     time_2=`date +%s%N`
     durtime=`echo $time_2 $time_1 | awk '{printf "%0.3f\n", ($1 - $2) / 1000000000}'`
     echo "tpch_queries_$i.sql warmup ${j} times END, COST: ${durtime}s"
   else
     time_1=`date +%s%N`
     echo `date  '+[%Y-%m-%d %H:%M:%S]'` "BEGIN RUN TPC-H Q${i} ${j} times" >> ./${logdir}/run-tpch-queries.log 2>&1
     $MYSQL_CLI < ./queries/tpch_queries_$i.sql >> ./${logdir}/tpch_queries_${i}_${j}.res 2>&1
     time_2=`date +%s%N`
     durtime=`echo $time_2 $time_1 | awk '{printf "%0.3f\n", ($1 - $2) / 1000000000}'`
     echo `date  '+[%Y-%m-%d %H:%M:%S]'` "TPC-H Q${i} END, COST: ${durtime}s" >> ./${logdir}/run-tpch-queries.log 2>&1
     echo "RUN TPC-H Q${i} ${j} times END, COST: ${durtime}s"
     echo "" >> ./${logdir}/run-tpch-queries.log 2>&1
     echo "" >> ./${logdir}/run-tpch-queries.log 2>&1
   fi
   echo "sleeping for ${sleeptime} seconds"
   sleep ${sleeptime}
 done
done
 2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
这个脚本最新版本可以看这里 TPC-H 自动测试脚本 run-tpch.sh (opens new window)。
在运行查询SQL时,也要观察相关指标:
greatsql> SHOW GLOBAL STATUS LIKE 'Secondary_engine_execution_count';
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| Secondary_engine_execution_count | 41    |
+----------------------------------+-------+
 2
3
4
5
6
上述结果中的 Secondary_engine_execution_count 状态指标值为 41,表示共发生了 41 次辅助引擎(Rapid)的读取请求。
§ 测试结果
在 GreatSQL 8.0.32-25 中引入了 Rapid 辅助引擎,对 TB 数据量级的 OLAP 复杂数据分析类型查询有很好的优化效果,其查询效率也在不断提升中。
在最近的测试中,利用 Rapid 引擎运行 TPC-H SF100/SF1000 数据量级测试时,总耗时分别为:39.399 和 642.652 秒。
| 测试数据量 | Q1 | Q2 | Q3 | Q4 | Q5 | Q6 | Q7 | Q8 | Q9 | Q10 | Q11 | Q12 | Q13 | Q14 | Q15 | Q16 | Q17 | Q18 | Q19 | Q20 | Q21 | Q22 | 总耗时 | 
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| TPC-H SF100 | 3.218 | 0.305 | 1.036 | 0.868 | 1.011 | 0.219 | 4.469 | 0.886 | 3.030 | 2.597 | 0.164 | 0.588 | 2.760 | 0.729 | 0.986 | 0.654 | 0.739 | 9.557 | 1.422 | 0.624 | 3.006 | 0.531 | 39.399 | 
| TPC-H SF1000 | 17.713 | 2.221 | 6.710 | 6.297 | 6.783 | 1.373 | 63.600 | 5.589 | 37.384 | 38.240 | 1.299 | 5.039 | 29.492 | 5.269 | 8.209 | 4.748 | 4.910 | 358.120 | 7.938 | 3.788 | 23.485 | 4.445 | 642.652 | 
上述数据的测试机配置为 32C64G、NVMe PCIe SSD 3.8T。
更多关于 GreatSQL 的 TPC-H 测试的详细信息可参考:GreatSQL TPC-H 性能测试报告。
扫码关注微信公众号
