本文详细介绍了PolarDB-X的TPC-H测试设计、测试过程和测试结果。

TPC-H说明

TPC-H是业界常用的一套Benchmark,由TPC委员会制定发布,用于评测数据库的分析型查询能力。TPC-H查询包含8张数据表、22条复杂的SQL查询,大多数查询包含若干表Join、子查询和Group-by聚合等。

说明 本文的TPC-H的实现基于TPC-H的基准测试,并不能与已发布的TPC-H基准测试结果相比较,本文中的测试并不符合TPC-H基准测试的所有要求。

测试设计

  • 企业版测试环境:PolarDB-X计算资源DRDS实例企业版32C128G(单节点16C64G)、4台RDS MySQL 5.7实例(8C32G独享型)。
  • 标准版测试环境:PolarDB-X计算资源DRDS实例标准版16C64G(单节点8C32G)、4台RDS MySQL 5.7实例(4C32G 独享型)。

以下测试结果基于50G数据量(Scalar Factor = 50),其中主要表数据量如下:LINEITEM表约3亿行,ORDERS表7500万行,PARSUPP表4000万行。

以Q18为例,包含4张千万到亿级表的Join(含一个子查询SemiJoin)和Group-by聚合。在PolarDB-X计算资源DRDS实例上查询执行时间约11秒。

select c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice, sum(l_quantity)
from CUSTOMER, ORDERS, LINEITEM
where o_orderkey in (
        select l_orderkey
        from LINEITEM
        group by l_orderkey
        having sum(l_quantity) > 314
    )
    and c_custkey = o_custkey
    and o_orderkey = l_orderkey
group by c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice
order by o_totalprice desc, o_orderdate
limit 100;

测试过程

说明 以下测试过程依赖了LoadData功能做TPH数据导入,该功能要求内核版本>=5.4.7-16000638。
  1. 准备压力机ECS。这是以下所有操作的基础,准备数据、运行压测等都需在这台ECS上进行。
    说明
    • 建议选择VPC网络,经典网络有可能遇到RDS某些规格没有库存。请记录VPC的ID和名称,之后所有的实例和数据都部署在这个VPC里面。
    • 建议使用最新的Debian或者CentOS镜像,防止编译时缺少依赖库。
  2. 创建PolarDB-X计算资源DRDS实例以及相应的RDS实例,注意必须和上一步骤创建的ECS在同一个VPC中。
  3. 在PolarDB-X计算资源DRDS实例上创建库和表,注意要指定分库分表方式,建议使用以下表结构:
    CREATE TABLE `customer` (
      `c_custkey` int(11) NOT NULL,
      `c_name` varchar(25) NOT NULL,
      `c_address` varchar(40) NOT NULL,
      `c_nationkey` int(11) NOT NULL,
      `c_phone` varchar(15) NOT NULL,
      `c_acctbal` decimal(15,2) NOT NULL,
      `c_mktsegment` varchar(10) NOT NULL,
      `c_comment` varchar(117) NOT NULL,
      PRIMARY KEY (`c_custkey`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 dbpartition by hash(`c_custkey`) tbpartition by hash(`c_custkey`) tbpartitions 4;
    CREATE TABLE `lineitem` (
      `l_orderkey` bigint(20) NOT NULL,
      `l_partkey` int(11) NOT NULL,
      `l_suppkey` int(11) NOT NULL,
      `l_linenumber` bigint(20) 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` varchar(1) NOT NULL,
      `l_linestatus` varchar(1) NOT NULL,
      `l_shipdate` date NOT NULL,
      `l_commitdate` date NOT NULL,
      `l_receiptdate` date NOT NULL,
      `l_shipinstruct` varchar(25) NOT NULL,
      `l_shipmode` varchar(10) NOT NULL,
      `l_comment` varchar(44) NOT NULL,
      KEY `IDX_LINEITEM_PARTKEY` (`l_partkey`),
      PRIMARY KEY (`l_orderkey`,`l_linenumber`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 dbpartition by RIGHT_SHIFT(`l_orderkey`,6) tbpartition by RIGHT_SHIFT(`l_orderkey`,6) tbpartitions 4;
    CREATE TABLE `orders` (
      `o_orderkey` bigint(20) NOT NULL,
      `o_custkey` int(11) NOT NULL,
      `o_orderstatus` varchar(1) NOT NULL,
      `o_totalprice` decimal(15,2) NOT NULL,
      `o_orderdate` date NOT NULL,
      `o_orderpriority` varchar(15) NOT NULL,
      `o_clerk` varchar(15) NOT NULL,
      `o_shippriority` bigint(20) NOT NULL,
      `o_comment` varchar(79) NOT NULL,
      PRIMARY KEY (`O_ORDERKEY`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 dbpartition by RIGHT_SHIFT(`O_ORDERKEY`,6) tbpartition by RIGHT_SHIFT(`O_ORDERKEY`,6) tbpartitions 4;
    CREATE TABLE `part` (
      `p_partkey` int(11) NOT NULL,
      `p_name` varchar(55) NOT NULL,
      `p_mfgr` varchar(25) NOT NULL,
      `p_brand` varchar(10) NOT NULL,
      `p_type` varchar(25) NOT NULL,
      `p_size` int(11) NOT NULL,
      `p_container` varchar(10) NOT NULL,
      `p_retailprice` decimal(15,2) NOT NULL,
      `p_comment` varchar(23) NOT NULL,
      PRIMARY KEY (`p_partkey`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 dbpartition by hash(`p_partkey`) tbpartition by hash(`p_partkey`) tbpartitions 4;
    CREATE TABLE `partsupp` (
      `ps_partkey` int(11) NOT NULL,
      `ps_suppkey` int(11) NOT NULL,
      `ps_availqty` int(11) NOT NULL,
      `ps_supplycost` decimal(15,2) NOT NULL,
      `ps_comment` varchar(199) NOT NULL,
      KEY `IDX_PARTSUPP_SUPPKEY` (`PS_SUPPKEY`),
      PRIMARY KEY (`ps_partkey`,`ps_suppkey`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 dbpartition by hash(`ps_partkey`) tbpartition by hash(`ps_partkey`) tbpartitions 4;
    CREATE TABLE `supplier` (
      `s_suppkey` int(11) NOT NULL,
      `s_name` varchar(25) NOT NULL,
      `s_address` varchar(40) NOT NULL,
      `s_nationkey` int(11) NOT NULL,
      `s_phone` varchar(15) NOT NULL,
      `s_acctbal` decimal(15,2) NOT NULL,
      `s_comment` varchar(101) NOT NULL,
      PRIMARY KEY (`s_suppkey`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 dbpartition by hash(`s_suppkey`) tbpartition by hash(`s_suppkey`) tbpartitions 4;
    CREATE TABLE `nation` (
      `n_nationkey` int(11) NOT NULL,
      `n_name` varchar(25) NOT NULL,
      `n_regionkey` int(11) NOT NULL,
      `n_comment` varchar(152) DEFAULT NULL,
      PRIMARY KEY (`n_nationkey`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 broadcast;
    CREATE TABLE `region` (
      `r_regionkey` int(11) NOT NULL,
      `r_name` varchar(25) NOT NULL,
      `r_comment` varchar(152) DEFAULT NULL,
      PRIMARY KEY (`r_regionkey`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 broadcast;
  4. 准备导入数据到PolarDB-X计算资源DRDS实例。将脚本下载至压力机ECS上,下载链接:tpchData.zip
    #解压tpchData.zip 脚本
    unzip tpchData.zip
    cd tpchData
    #编辑conf文件
    vim param.conf

    将conf文件中最后一行的连接信息改成真实的连接信息。

    #!/bin/bash
    
    ### remote generating directory
    export remoteGenDir=./
    
    ### target path
    export targetPath=../tpch/tpchRaw
    export sourcePath=../tpch/tpchRaw
    
    ### cores per worker, default value is 1
    export coresPerWorker=1
    
    ### threads per worker, default value is 1
    export threadsPerWorker=1
    
    export hint=""
    ###如果需要测试其他规模的数量级,比如100G的话,则数据库名换成tpch_100g
    export insertMysql="mysql -hxxxxxxxxxx.drds.aliyuncs.com -P3306 -uxxx -pxxxxxx -Ac --local-infile tpch_50g -e"

    生成50G的数据。

    cd workloads
    #编辑生成各个表数据的文件数量
    cp tpch.workload.1.lst tpch.workload.50.lst
    #进入上层目录datagen
    cd datagen
    #生成数据,这个步骤只需执行一次,后续如果有重复准备数据,可以不再重复执行
    sh generateTPCH.sh 50
    #将数据载入PolarDB-X计算资源DRDS实例
    cd ../loadTpch
    sh loadTpch.sh 50

    验证数据正确性。

    MySQL [tpch_5g]> select (select count(*) from customer) as customer_cnt,
        ->        (select count(*)  from lineitem) as lineitem_cnt,
        ->        (select count(*)  from nation) as nation_cnt,
        ->        (select count(*)  from orders) as order_cnt,
        ->        (select count(*) from part) as part_cnt,
        ->        (select count(*) from partsupp) as partsupp_cnt,
        ->        (select count(*) from region) as region_cnt,
        ->        (select count(*) from supplier) as supplier_cnt;
  5. 运行TPCH 测试前,使用 ANALYZE 命令采集统计信息。
    analyze table customer;
    analyze table lineitem;
    analyze table nation;
    analyze table orders;
    analyze table part;
    analyze table partsupp;
    analyze table region;
    analyze table supplier;
  6. 测试。
    cd tpchData
    cd runTpch
    sh runTpch.sh
    #运行结束进入result_fixed_mget,查看各条sql成绩
    cd result_fixed_mget

测试结果

说明 PolarDB-X计算资源DRDS实例入门版不具备Parallel Query能力,不建议用于执行分析型查询。
2021051301
Query 企业版(单位:秒) 标准版(单位:秒)
Q01 55.82 111.84
Q02 6.12 11.54
Q03 15.99 30
Q04 17.71 36.56
Q05 10.89 23.01
Q06 8.06 16.76
Q07 17.09 34.80
Q08 13.44 26.09
Q09 53.81 101.51
Q10 8.73 19.67
Q11 18.25 19.74
Q12 8.80 18.60
Q13 14.15 31.33
Q14 17.49 42.43
Q15 20.62 42.79
Q16 2.13 4.15
Q17 1.93 4.07
Q18 11.01 22.82
Q19 12.97 27.61
Q20 27.77 49.25
Q21 38.84 68.08
Q22 5.27 11.29
总计 386.77 754.65