---
title: "OceanBase 数据库 TPC-H 测试 - OceanBase 数据库 V4.3.5 | OceanBase 文档中心"
description: OceanBase 数据库 TPC-H 测试 本文介绍基于 OceanBase 数据库进行 TPC-H 测试时，所需的软件要求、租户规格配置，以及详细的测试方法。 什么是 TPC-H TPC-H（商业智能计算测试）是美国交易处理效能委员会（TPC，Transaction Processing Performance …
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

文档反馈![](https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*P8CuR4UJ_FkAAAAAAAAAAAAADiGDAQ/original) OceanBase 数据库分布式版 - V 4.3.5 LTS

# OceanBase 数据库 TPC-H 测试

更新时间：2026-04-07 20:57:20

[编辑](https://github.com/oceanbase/oceanbase-doc/edit/V4.3.5/zh-CN/700.reference/1100.performance-test/500.tpc-h-benchmark-testing-on-oceanbase-database/100.run-the-tpc-h-benchmark-on-oceanbase-database.md)  

本文介绍基于 OceanBase 数据库进行 TPC-H 测试时，所需的软件要求、租户规格配置，以及详细的测试方法。

## 什么是 TPC-H

TPC-H（商业智能计算测试）是美国交易处理效能委员会（TPC，Transaction Processing Performance Council）组织制定的用来模拟决策支持类应用的一个测试集。目前，学术界和工业界普遍采用 TPC-H 来评价决策支持技术方面应用的性能。这种商业测试可以全方位评测系统的整体商业计算综合能力，对厂商的要求更高，同时也具有普遍的商业实用意义，目前在银行信贷分析和信用卡分析、电信运营分析、税收分析、烟草行业决策分析中都有广泛的应用。

TPC-H 基准测试由 TPC-D（由 TPC 于 1994 年制定的标准，用于决策支持系统方面的测试基准）发展而来的。TPC-H 用 3NF 实现了一个数据仓库，共包含 8 个基本关系，其主要评价指标是各个查询的响应时间，即从提交查询到结果返回所需时间。TPC-H 基准测试的度量单位是每小时执行的查询数（QphH@size），其中 H 表示每小时系统执行复杂查询的平均次数，size 表示数据库规模的大小，它能够反映出系统在处理查询时的能力。TPC-H 是根据真实的生产运行环境来建模的，这使得它可以评估一些其他测试所不能评估的关键性能参数。总而言之，TPC 组织颁布的TPC-H 标准满足了数据仓库领域的测试需求，并且促使各个厂商以及研究机构将该项技术推向极限。

#### 说明

为了提升用户体验和易用性，让每一个开发者在使用数据库时都能获得较好的性能，OceanBase 数据库在 V4.0.0 版本之后，做了大量的优化工作。本性能测试方法仅基于基础参数进行调优，让开发者获得较好的数据库性能体验。

## 环境准备

测试前请按照如下要求进行测试环境准备：

#### 说明

该示例以 MySQL 租户为例。

### 软件要求

- JDK：建议使用 1.8u131 及以上版本。
 - make：执行 `yum install make` 命令安装。
 - GCC：执行 `yum install gcc` 命令安装。
 - mysql-devel：执行 `yum install mysql-devel` 命令安装。
 - Python 连接数据库的驱动：执行 `sudo yum install MySQL-python` 命令安装。
 - prettytable：执行 `pip install prettytable` 命令安装。
 - JDBC：建议使用 `mysql-connector-java-5.1.47` 版本。
 - TPC-H Tool：点击 [下载地址](https://www.tpc.org/tpc_documents_current_versions/download_programs/tools-download-request5.asp?bm_type=TPC-H&bm_vers=3.0.0&mode=CURRENT-ONLY) 获取，如果使用 OBD 一键测试，可以跳过该工具。
 - OBClient：详细信息，请参考 [OBClient 文档](https://github.com/oceanbase/obclient/blob/master/README.md)。
 - OceanBase 数据库：详细信息，请参考 [快速体验 OceanBase 数据库](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000002012693)。
 - IOPS：建议磁盘 IOPS 在 10000 以上。

### 租户规格配置

租户规格是基于 [OceanBase数据库 TPC-H 测试报告](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000002506676) 中的硬件配置进行配置的，您需要根据自身数据库的硬件配置进行动态调整。

- **集群部署**

     1. 本次测试需要用到 4 台机器，TPC-H 和 OBD 单独部署在一台机器上，作为客户端的压力机器。通过 OBD 部署 OceanBase 集群需要使用 3 台机器，OceanBase 集群规模为 1:1:1。

       #### 说明

            - 在 TPC-H 测试中，部署 TPC-H 和 OBD 的机器只需 4 核 16G 即可。
            - 部署集群时，建议不要使用 `obd cluster autodeploy` 命令，该命令为了保证稳定性，不会最大化资源利用率（例如不会使用所有内存），建议单独对配置文件进行调优，最大化资源利用率。
     2. 部署成功后，新建执行 TPC-H 测试的租户及用户（sys 租户是管理集群的内置系统租户，请勿直接使用 sys 租户进行测试）。将租户的 `primary_zone` 设置为 `RANDOM`。`RANDOM` 表示新建表分区的 Leader 随机到这 3 台机器。
 - **租户创建**

  可以通过 `OBD CLUSTER TENANT CREATE` 命令创建测试租户，对应的 SQL 语法如下：

  ```sql
  obd cluster tenant create <DEPLOY_NAME> -n <TENANT_NAME> --max-cpu=28 --memory-size=180G -–zone-list=zone1,zone2,zone3 -–primary-zone=RANDOM  --locality=F@zone1,F@zone2,F@zone3 --charset=utf8 -s 'ob_tcp_invited_nodes="%"' --optimize=<optimize>

  ```

  参数解释如下：

     - `DEPLOY_NAME`：集群名称。
     - `TENANT_NAME`：租户名称。
     - `--zone-list`：租户的 Zone 列表。
     - `--primary-zone`：租户的主 Zone。
     - `--locality`：副本在 Zone 间的分布情况。
     - `--charset`：租户的字符集。
     - `-s`：租户系统变量值。
     - `OPTIMIZE`：租户负载类型，包括 `express_oltp`、`complex_oltp`、`olap`、`htap`、 `kv` 五种负载类型，默认负载类型为 `htap`，适用于混合 OLAP 和 OLTP 工作负载。有关 OBD 部署的更多内容，参见 [obd cluster tenant create](https://www.oceanbase.com/docs/community-obd-cn-1000000000955364)。

      #### 注意

      对于 V4.3.x 及之后版本，在使用 OBD 部署时，可以通过设置配置项 `scenario` 选择合适的集群负载类型，未配置的情况下默认 `scenario` 为 `htap`。更多内容请参见 [OBD 部署 OceanBase 数据库](https://www.oceanbase.com/docs/community-obd-cn-1000000000955369)。

  例如创建一个名为 `tpch_tenant` 的租户，其所使用的集群名为 `obperf`，具有 28 核 CPU 和 180GB 内存的资源配置，并设置默认租户的负载类型与集群的场景保持一致。

  ```shell
  obd cluster tenant create obperf -n tpch_tenant --max-cpu=28 --memory-size=180G -–zone-list=zone1,zone2,zone3 -–primary-zone=RANDOM  --locality=F@zone1,F@zone2,F@zone3 --charset=utf8 -s 'ob_tcp_invited_nodes="%"' --optimize=htap

  ```

  #### 说明

  本示例中 `--optimize=htap` 为默认负载类型，在生产环境中请根据实际的集群类型来选择合适的负载类型。

## 测试方法

测试环境准备好后，可基于以下 2 种方法进行 TPC-H 性能测试：

- **使用 OBD 工具一键执行 TPC-H 测试**
 - **使用 TPC-H 工具手动执行 TPC-H 测试**

### 使用 OBD 工具一键执行 TPC-H 测试

可通过 OBD 脚本一键执行 TPC-H 测试，脚本命令如下：

```shell
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/oceanbase/OceanBase.repo
sudo yum install obtpch
sudo ln -s /usr/tpc-h-tools/tpc-h-tools/ /usr/local/
obd test tpch obperf  --tenant=tpch_mysql -s 100 --remote-tbl-dir=/tmp/tpch100

```

使用上述脚本进行 TPC-H 测试前，需要注意以下事项：

- 使用 OBD 运行 TPC-H 的详细参数内容，请参考 [obd test tpch](https://www.oceanbase.com/docs/community-obd-cn-10000000001031935)。
 - 在本例中，大部分参数使用的是默认参数，在用户场景下，可以根据自己的具体情况做一些参数上的调整。例如，在本例中使用的集群名为 `obperf`，租户名是 `tpch_mysql`。
 - 使用 OBD 进行一键测试时，集群的部署必须是由 OBD 进行安装和部署，否则无法获取集群的信息，将导致无法根据集群的配置进行性能调优。
 - 如果系统租户的密码通过终端登录并修改，非默认空值，则需要您先在终端中将密码修改为默认值，之后通过 [obd cluster edit-config](https://www.oceanbase.com/docs/community-obd-cn-10000000001031935) 命令在配置文件中为系统租户设置密码，配置项是 `# root_password: # root user password`。在 `obd cluster edit-config` 命令执行结束后，您还需执行 `obd cluster reload` 命令使修改生效。
 - 运行 `obd test tpch` 后，系统会详细列出运行步骤和输出，数据量越大耗时越久。
 - `remote-tbl-dir` 远程目录具备足够的容量能存储 tpch 的数据，建议单独一块盘存储加载测试数据。
 - `obd test tpch` 命令会自动完成所有操作，无需其他额外任何操作，包含测试数据的生成、传送、OceanBase 参数优化、加载和测试。当中间环节出错时，您可参考 [obd test tpch](https://www.oceanbase.com/docs/community-obd-cn-10000000001031935) 进行重试。例如：跳过数据的生成和传送，直接进行加载和测试。

### 使用 TPC-H 工具手动执行 TPC-H 测试

手动测试在选定集群负载类型和租户调优场景后进行，有助于深入掌握 OceanBase 数据库，特别是参数设置的优化。

#### 步骤一：创建测试租户

#### 说明

若测试租户已在环境准备阶段完成创建，可跳过本步骤。

在系统租户（`sys` 租户）下执行的命令创建测试租户：

#### 说明

本次测试的 OceanBase 集群环境部署模式为 1:1:1。

1. 创建资源单元 `mysql_box`。

   ```sql
   CREATE RESOURCE UNIT mysql_box
      MAX_CPU 28,
      MEMORY_SIZE '200G',
      MIN_IOPS 200000,
      MAX_IOPS 12800000,
      LOG_DISK_SIZE '300G';

   ```
 2. 创建资源池 `mysql_pool`。

   ```sql
   CREATE RESOURCE POOL mysql_pool
      UNIT = 'mysql_box',
      UNIT_NUM = 1,
      ZONE_LIST = ('z1','z2','z3');

   ```
 3. 创建 MySQL 模式租户 `mysql_tenant`。

   ```sql
   CREATE TENANT mysql_tenant
      RESOURCE_POOL_LIST = ('mysql_pool'),
      PRIMARY_ZONE = RANDOM,
      LOCALITY = 'F@z1,F@z2,F@z3'
      SET VARIABLES ob_compatibility_mode='mysql', ob_tcp_invited_nodes='%', secure_file_priv = "/";

   ```

#### 步骤二：进行环境调优

1. OceanBase 数据库调优。

   请在系统租户（`sys` 租户）下执行以下语句配置相关参数。

   ```sql
   ALTER SYSTEM FLUSH PLAN CACHE GLOBAL;
   ALTER SYSTEM SET enable_sql_audit = false;
   SELECT sleep(5);
   ALTER SYSTEM SET enable_perf_event = false;
   ALTER SYSTEM SET syslog_level = 'PERF';
   ALTER SYSTEM SET enable_record_trace_log = false;
   ALTER SYSTEM SET data_storage_warning_tolerance_time = '300s';
   ALTER SYSTEM SET _data_storage_io_timeout = '600s';
   ALTER SYSTEM SET trace_log_slow_query_watermark = '7d';
   ALTER SYSTEM SET large_query_threshold = '0ms';
   ALTER SYSTEM SET enable_syslog_recycle = 1;
   ALTER SYSTEM SET max_syslog_file_count = 300;

   ```
 2. 租户调优。

   请在测试租户（用户租户）下执行以下语句配置相关参数。

   ```sql
   SET GLOBAL NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
   SET GLOBAL NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF';
   SET GLOBAL NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF TZR TZD';

   SET GLOBAL ob_query_timeout = 10800000000;
   SET GLOBAL ob_trx_timeout = 10000000000;

   SET GLOBAL ob_sql_work_area_percentage = 50;
   ALTER SYSTEM SET default_table_store_format = 'column' ;
   ALTER SYSTEM SET ob_enable_batched_multi_statement = 'true';
   ALTER SYSTEM SET _io_read_batch_size = '128k';
   ALTER SYSTEM SET _io_read_redundant_limit_percentage = 50;
   SET GLOBAL parallel_degree_policy = AUTO;
   SET GLOBAL parallel_servers_target = 10000;

   SET GLOBAL collation_connection = utf8mb4_bin;
   SET GLOBAL collation_database = utf8mb4_bin;
   SET GLOBAL collation_server = utf8mb4_bin;

   SET GLOBAL autocommit = 1;

   ALTER SYSTEM SET ob_enable_batched_multi_statement = 'true';

   ```

#### 步骤三：安装 TPC-H Tool

1. 下载 TPC-H Tool。详细信息请参考 [TPC-H Tool 下载页面](https://www.tpc.org/tpc_documents_current_versions/download_programs/tools-download-request5.asp?bm_type=TPC-H&bm_vers=3.0.0&mode=CURRENT-ONLY)。
 2. 下载完成后解压文件，进入 TPC-H 解压后的目录。

   ```bash
   [wieck@localhost ~] $ unzip 7e965ead-8844-4efa-a275-34e35f8ab89b-tpc-h-tool.zip
   [wieck@localhost ~] $ cd TPC-H_Tools_v3.0.0

   ```
 3. 复制 `Makefile.suite`。

   ```bash
   [wieck@localhost TPC-H_Tools_v3.0.0] $ cd dbgen/
   [wieck@localhost dbgen] $ cp Makefile.suite Makefile

   ```
 4. 修改 `Makefile` 文件中的 `CC`、`DATABASE`、`MACHINE`、`WORKLOAD` 等参数定义。

   ```bash
   [wieck@localhost dbgen] $ vim Makefile

   ```

   ```bash
   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

   ```
 5. 修改 `tpcd.h` 文件，并添加新的宏定义。

   ```bash
   [wieck@localhost dbgen] $ vim tpcd.h

   ```

   ```bash
   #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

   ```
 6. 编译文件。

   ```bash
   make

   ```

   返回结果如下：

   ```bash
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o build.o build.c
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o driver.o driver.c
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o bm_utils.o bm_utils.c
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o rnd.o rnd.c
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o print.o print.c
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o load_stub.o load_stub.c
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o bcd2.o bcd2.c
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o speed_seed.o speed_seed.c
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o text.o text.c
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o permute.o permute.c
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o rng64.o rng64.c
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64  -O -o dbgen build.o driver.o bm_utils.o rnd.o print.o load_stub.o bcd2.o speed_seed.o text.o permute.o rng64.o -lm
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o qgen.o qgen.c
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64    -c -o varsub.o varsub.c
   gcc  -g -DDBNAME=\"dss\" -DLINUX -DMYSQL -DTPCH -DRNG_TEST -D_FILE_OFFSET_BITS=64  -O -o qgen build.o bm_utils.o qgen.o rnd.o varsub.o text.o bcd2.o permute.o speed_seed.o rng64.o -lm

   ```

   会生成后续生成数据的 dbgen 文件和生成 sql 的 qgen、dists.dss 文件。

#### 步骤四：生成数据

您可以根据实际环境生成 TPC-H 10G、100G 或者 1T 数据。本文以生成 100G 数据为例。

```bash
./dbgen -s 100
mkdir tpch100
mv *.tbl tpch100

```

多线程生成 1T 数据，Oceanbase 支持旁路导入数据，可以同时将多个文件的数据导入表中：

```bash
#!/bin/bash  

SCALE_FACTOR=1000  
CHUNK_COUNT=20  
for ((i=1; i<=CHUNK_COUNT; i++))  
do
   CMD="./dbgen -s ${SCALE_FACTOR} -C ${CHUNK_COUNT} -S ${i} -vf"
   $CMD &  
done  
wait  
echo "All data generation tasks completed."

```

#### 步骤五：生成查询 SQL

#### 说明

您可参考本节中的下述步骤生成查询 SQL 后进行调整，也可直接使用 [GitHub](https://github.com/oceanbase/obdeploy/tree/master/plugins/tpch/4.3.0.0/queries) 中给出的查询 SQL。若您选择使用 GitHub 中的查询 SQL，您需将 SQL 语句中的 `cpu_num`修改为实际并发数。

使用 TCP-H 自带工具生成，步骤如下：

1. 将 `dbgen/qgen` 和 `dbgen/dists.dss` 拷贝到 `mysql_sql` 文件夹下。
 2. 在 `mysql_sql` 文件夹下创建 `gen.sh` 脚本生成查询 SQL。

   ```bash
   vim gen.sh

   ```

   ```bash
   #!/usr/bin/bash
   for i in {1..22}
   do  
   ./qgen -d $i -s 100 > db"$i".sql
   done

   ```
 3. 按照实际并发数修改查询 SQL。

   您可在 `sys` 租户下使用如下命令查看租户的可用 CPU 总数。

   ```sql
   select sum(max_cpu) from DBA_OB_UNITS;

   ```

   以 `Q1` 为例，修改后的 SQL 语句如下：

   ```sql
   SELECT /*+    parallel(96) */   ---增加 parallel 并发执行
   l_returnflag,
   l_linestatus,
   sum(l_quantity) as sum_qty,
   sum(l_extendedprice) as sum_base_price,
   sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
   sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge,
   avg(l_quantity) as avg_qty,
   avg(l_extendedprice) as avg_price,
   avg(l_discount) as avg_disc,
   count(*) as count_order
   FROM
   lineitem
   WHERE
   l_shipdate <= date '1998-12-01' - interval '90' day
   GROUP BY
   l_returnflag,
   l_linestatus
   ORDER BY
   l_returnflag,
   l_linestatus;

   ```

#### 步骤六：新建表

- 100G 数据，创建表结构文件 `create_tpch_mysql_table_part.ddl`。

  ```bash
  drop tablegroup IF EXISTS tpch_tg_SF_TPC_USER_lineitem_order_group;
  drop tablegroup IF EXISTS  tpch_tg_SF_TPC_USER_partsupp_part;
  create tablegroup tpch_tg_SF_TPC_USER_lineitem_order_group binding true partition by key 1 partitions 256;
  create tablegroup tpch_tg_SF_TPC_USER_partsupp_part binding true partition by key 1 partitions 256;

  DROP TABLE IF EXISTS LINEITEM;
  CREATE TABLE lineitem (
     l_orderkey int(11) NOT NULL,
     l_partkey int(11) NOT NULL,
     l_suppkey int(11) NOT NULL,
     l_linenumber int(11) 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) DEFAULT NULL,
     l_linestatus char(1) DEFAULT NULL,
     l_shipdate date NOT NULL,
     l_commitdate date DEFAULT NULL,
     l_receiptdate date DEFAULT NULL,
     l_shipinstruct varchar(25) DEFAULT NULL,
     l_shipmode varchar(10) DEFAULT NULL,
     l_comment varchar(44) DEFAULT NULL,
  primary key(l_shipdate, l_orderkey, l_linenumber)
  )row_format = condensed
  tablegroup = tpch_tg_SF_TPC_USER_lineitem_order_group
  partition by key (l_orderkey) partitions 256 with column group(each column);
  alter table lineitem CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

  DROP TABLE IF EXISTS ORDERS;
  CREATE TABLE orders (
     o_orderkey int(11) NOT NULL,
     o_custkey int(11) NOT NULL,
     o_orderstatus varchar(1) DEFAULT NULL,
     o_totalprice decimal(15,2) DEFAULT NULL,
     o_orderdate date NOT NULL,
     o_orderpriority varchar(15) DEFAULT NULL,
     o_clerk varchar(15) DEFAULT NULL,
     o_shippriority int(11) DEFAULT NULL,
     o_comment varchar(79) DEFAULT NULL,
  PRIMARY KEY (o_orderkey, o_orderdate)
  ) row_format = condensed
  tablegroup = tpch_tg_SF_TPC_USER_lineitem_order_group
  partition by key(o_orderkey) partitions 256 with column group(each column);
  alter table orders CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

  DROP TABLE IF EXISTS PARTSUPP;
  CREATE TABLE partsupp (
     ps_partkey int(11) NOT NULL,
     ps_suppkey int(11) NOT NULL,
     ps_availqty int(11) DEFAULT NULL,
     ps_supplycost decimal(15,2) DEFAULT NULL,
     ps_comment varchar(199) DEFAULT NULL,
     PRIMARY KEY (ps_partkey, ps_suppkey)) row_format = condensed
  tablegroup tpch_tg_SF_TPC_USER_partsupp_part
  partition by key(ps_partkey) partitions 256 with column group(each column);
  alter table partsupp CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

  DROP TABLE IF EXISTS PART;
  CREATE TABLE part (
  p_partkey int(11) NOT NULL,
  p_name varchar(55) DEFAULT NULL,
  p_mfgr varchar(25) DEFAULT NULL,
  p_brand varchar(10) DEFAULT NULL,
  p_type varchar(25) DEFAULT NULL,
  p_size int(11) DEFAULT NULL,
  p_container varchar(10) DEFAULT NULL,
  p_retailprice decimal(12,2) DEFAULT NULL,
  p_comment varchar(23) DEFAULT NULL,
  PRIMARY KEY (p_partkey)) row_format = condensed
  tablegroup tpch_tg_SF_TPC_USER_partsupp_part
  partition by key(p_partkey) partitions 256 with column group(each column);
  alter table part CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

  DROP TABLE IF EXISTS CUSTOMER;
  CREATE TABLE customer (
  c_custkey int(11) NOT NULL,
  c_name varchar(25) DEFAULT NULL,
  c_address varchar(40) DEFAULT NULL,
  c_nationkey int(11) DEFAULT NULL,
  c_phone varchar(15) DEFAULT NULL,
  c_acctbal decimal(15,2) DEFAULT NULL,
  c_mktsegment char(10) DEFAULT NULL,
  c_comment varchar(117) DEFAULT NULL,
  PRIMARY KEY (c_custkey)) row_format = condensed
  partition by key(c_custkey) partitions 256 with column group(each column);
  alter table customer CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

  DROP TABLE IF EXISTS SUPPLIER;
  CREATE TABLE supplier (
  s_suppkey int(11) NOT NULL,
  s_name varchar(25) DEFAULT NULL,
  s_address varchar(40) DEFAULT NULL,
  s_nationkey int(11) DEFAULT NULL,
  s_phone varchar(15) DEFAULT NULL,
  s_acctbal decimal(15,2) DEFAULT NULL,
  s_comment varchar(101) DEFAULT NULL,
  PRIMARY KEY (s_suppkey)
  ) row_format = condensed partition by key(s_suppkey) partitions 256 with column group(each column);
  alter table supplier CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

  DROP TABLE IF EXISTS NATION;
  CREATE TABLE nation (
  n_nationkey int(11) NOT NULL,
  n_name varchar(25) DEFAULT NULL,
  n_regionkey int(11) DEFAULT NULL,
  n_comment varchar(152) DEFAULT NULL,
  PRIMARY KEY (n_nationkey)
  ) row_format = condensed with column group(each column);
  alter table nation CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

  DROP TABLE IF EXISTS REGION;
  CREATE TABLE region (
  r_regionkey int(11) NOT NULL,
  r_name varchar(25) DEFAULT NULL,
  r_comment varchar(152) DEFAULT NULL,
  PRIMARY KEY (r_regionkey)
  ) row_format = condensed with column group(each column);
  alter table region CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

  CREATE VIEW revenue0 AS
  SELECT l_suppkey as supplier_no,
           SUM(l_extendedprice * ( 1 - l_discount )) as total_revenue
              FROM   lineitem
              WHERE  l_shipdate >= DATE '1996-01-01'
                       AND l_shipdate < DATE '1996-04-01'
              GROUP  BY l_suppkey;

  ```
 - 1T 数据，创建表结构文件 `create_tpch_mysql_table_part_1000G.ddl`。

  ```bash
  drop tablegroup IF EXISTS tpch_tg_SF_TPC_USER_lineitem_order_group_1000;
  drop tablegroup IF EXISTS  tpch_tg_SF_TPC_USER_partsupp_part_1000;
  create tablegroup tpch_tg_SF_TPC_USER_lineitem_order_group_1000 binding true partition by key 1 partitions 256;
  create tablegroup tpch_tg_SF_TPC_USER_partsupp_part_1000 binding true partition by key 1 partitions 256;

  DROP TABLE IF EXISTS LINEITEM;
  CREATE TABLE lineitem (
     l_orderkey bigint NOT NULL,
     l_partkey int(32) NOT NULL,
     l_suppkey int(32) NOT NULL,
     l_linenumber int(32) NOT NULL,
     l_quantity decimal(32,2) NOT NULL,
     l_extendedprice decimal(32,2) NOT NULL,
     l_discount decimal(15,2) NOT NULL,
     l_tax decimal(15,2) NOT NULL,
     l_returnflag varchar(64) DEFAULT NULL,
     l_linestatus varchar(64) DEFAULT NULL,
     l_shipdate date NOT NULL,
     l_commitdate date DEFAULT NULL,
     l_receiptdate date DEFAULT NULL,
     l_shipinstruct varchar(64) DEFAULT NULL,
     l_shipmode varchar(64) DEFAULT NULL,
     l_comment varchar(64) DEFAULT NULL,
  primary key(l_shipdate, l_orderkey, l_linenumber)
  )row_format = condensed
  tablegroup = tpch_tg_SF_TPC_USER_lineitem_order_group_1000
  partition by key (l_orderkey) partitions 256 with column group(each column);
  alter table lineitem CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

  DROP TABLE IF EXISTS ORDERS;
  CREATE TABLE orders (
     o_orderkey bigint NOT NULL,
     o_custkey int(32) NOT NULL,
     o_orderstatus varchar(64) DEFAULT NULL,
     o_totalprice decimal(15,2) DEFAULT NULL,
     o_orderdate date NOT NULL,
     o_orderpriority varchar(15) DEFAULT NULL,
     o_clerk varchar(15) DEFAULT NULL,
     o_shippriority int(32) DEFAULT NULL,
     o_comment varchar(128) DEFAULT NULL,
  PRIMARY KEY (o_orderkey, o_orderdate)
  ) row_format = condensed
  tablegroup = tpch_tg_SF_TPC_USER_lineitem_order_group_1000
  partition by key(o_orderkey) partitions 256 with column group(each column);
  alter table orders CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

  DROP TABLE IF EXISTS PARTSUPP;
  CREATE TABLE partsupp (
     ps_partkey int(11) NOT NULL,
     ps_suppkey int(11) NOT NULL,
     ps_availqty int(11) DEFAULT NULL,
     ps_supplycost decimal(15,2) DEFAULT NULL,
     ps_comment varchar(199) DEFAULT NULL,
     PRIMARY KEY (ps_partkey, ps_suppkey)) row_format = condensed
  tablegroup tpch_tg_SF_TPC_USER_partsupp_part_1000
  partition by key(ps_partkey) partitions 256 with column group(each column);
  alter table partsupp CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

  DROP TABLE IF EXISTS PART;
  CREATE TABLE part (
  p_partkey int(11) NOT NULL,
  p_name varchar(55) DEFAULT NULL,
  p_mfgr varchar(25) DEFAULT NULL,
  p_brand varchar(10) DEFAULT NULL,
  p_type varchar(25) DEFAULT NULL,
  p_size int(11) DEFAULT NULL,
  p_container varchar(10) DEFAULT NULL,
  p_retailprice decimal(12,2) DEFAULT NULL,
  p_comment varchar(23) DEFAULT NULL,
  PRIMARY KEY (p_partkey)) row_format = condensed
  tablegroup tpch_tg_SF_TPC_USER_partsupp_part_1000
  partition by key(p_partkey) partitions 256 with column group(each column);
  alter table part CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

  ```

#### 步骤七：加载数据

您可以根据上述步骤生成的数据和 SQL 自行编写脚本。加载数据示例操作如下：

1. 创建加载数据的脚本 `load_data.sh`。

   ```bash
   #!/bin/bash
   host='$host_ip'   # 注意！！请填写某个 observer，如 observer A 所在服务器的 IP 地址, 最好将数据文件也放在该服务器下
   port='$host_port' # observer A 的端口号
   user='$user'      #  用户名
   tenant='$tenant_name'  # 租户名
   password='$password'   # 密码
   database='$db_name'    #  数据库名
   data_path='$data_file' # 注意！！请填写某个 observer，如 observer A 下在生成数据步骤中生成的数据文件.tbl路径

   function load_data
   {
      remote_user="$user"         # 存放数据的  observer  节点用户名
      table_name=${1}
      if [[ ${password} == "" ]];then
         obclient_conn="obclient -h${host} -P${port} -u${user} -D${database} -A -c"
      else
         obclient_conn="obclient -h${host} -P${port} -u${user} -D${database} -p${password} -A -c"
      fi
      table_list=$(ssh "${remote_user}@${host}" "ls ${data_path}/${table_name}.tbl* 2>/dev/null")  
      echo "$table_list"

      IFS=$'\n' read -d '' -r -a table_files <<< "$table_list"
      table_files_comma_separated=$(IFS=,; echo "${table_files[*]}")
      echo "${table_files_comma_separated}"
      echo `date "+[%Y-%m-%d %H:%M:%S]"` "----------------------正在导入${table_name}表的数据文件----------------------"

      # 使用旁路导入方式导入数据，也可自行修改为其他方式
      # 注意！！数据文件需存储在 OBServer 的测试机器上
      echo "load data /*+ parallel(80) direct(true,0) */ infile '${table_files_comma_separated}' into table ${table_name} fields terminated by '|';" | ${obclient_conn}

   }

   starttime=`date +%s%N`
   for table in "nation" "region" "customer" "lineitem" "orders" "partsupp" "part" "supplier"
   do
      load_data "${table}"
   done
   end_time=`date +%s%N`
   totaltime=`echo ${end_time} ${starttime} | awk '{printf "%0.2f\n", ($1 - $2) / 1000000000}'`
   echo `date "+[%Y-%m-%d %H:%M:%S]"` "load data cost ${totaltime}s"

   ```

   加载完数据后需进行合并和统计信息。
 2. 执行合并。

   在测试租户执行以下语句进行合并。

   ```sql
   ALTER SYSTEM MAJOR FREEZE;

   ```
 3. 查看合并是否完成。

   可以在 `sys` 租户下查看合并是否完成

   ```sql
   SELECT dt.TENANT_NAME, cc.FROZEN_SCN, cc.LAST_SCN
   FROM oceanbase.DBA_OB_TENANTS dt, oceanbase.CDB_OB_MAJOR_COMPACTION cc
   WHERE dt.TENANT_ID = cc.TENANT_ID
   AND dt.TENANT_NAME = 'mysql_tenant';

   ```

   #### 说明

   所有的 `FROZEN_SCN` 和 `LAST_SCN` 的值相等即表示合并完成。
 4. 执行收集统计信息。

   创建收集统计信息文件 `analyze_table.sql`。

   ```bash
   call dbms_stats.gather_table_stats(NULL, 'part', degree=>128, granularity=>'AUTO', method_opt=>'FOR ALL COLUMNS SIZE 128');
   call dbms_stats.gather_table_stats(NULL, 'lineitem', degree=>128, granularity=>'AUTO', method_opt=>'FOR ALL COLUMNS SIZE 128');
   call dbms_stats.gather_table_stats(NULL, 'customer', degree=>128, granularity=>'AUTO', method_opt=>'FOR ALL COLUMNS SIZE 128');
   call dbms_stats.gather_table_stats(NULL, 'orders', degree=>128, granularity=>'AUTO', method_opt=>'FOR ALL COLUMNS SIZE 128');
   call dbms_stats.gather_table_stats(NULL, 'partsupp', degree=>128, granularity=>'AUTO', method_opt=>'FOR ALL COLUMNS SIZE 128');
   call dbms_stats.gather_table_stats(NULL, 'supplier', degree=>128, granularity=>'AUTO', method_opt=>'FOR ALL COLUMNS SIZE 128');

   ```

   登录测试租户，执行以下语句进行收集统计信息：

   ```sql
   source analyze_table.sql

   ```

#### 步骤八：执行测试

您可以根据上述步骤生成的数据和 SQL 自行编写脚本。执行测试示例操作如下：

1. 编写测试脚本 `tpch.sh`。

   ```bash
   #!/bin/bash
   host='$host_ip'   # 注意！！请填写某个 observer，如 observer A 所在服务器的 IP 地址
   port='$host_port' # observer A 的端口号
   user='$user'      #  用户名
   tenant='$tenant_name'  # 租户名
   password='$password'   # 密码
   database='$db_name'    #  数据库名
   if [[ ${password} == "" ]];then
   TPCH_TEST="obclient -h${host} -P${port} -u${user}@{$tenant} -D${database} -A -c"
   else
   TPCH_TEST="obclient -h${host} -P${port} -p${password} -u${user}@{$tenant} -D${database} -A -c"
   fi

   function clear_kvcache
   {
      if [[ ${password_sys} == "" ]];then
         obclient_sys="obclient -h${host} -P${port} -uroot@sys -Doceanbase -A -c"
      else
         obclient_sys="obclient -h${host} -P${port} -uroot@sys -Doceanbase -p${password_sys} -A -c"
      fi
      tenant_name=${user#*@}
      echo "alter system flush kvcache ;" | ${obclient_sys}
      echo "alter system flush kvcache tenant '${tenant_name}' cache 'user_row_cache';" | ${obclient_sys}
      sleep 3s
   }

   function do_explain
   {
   #执行计划
   echo `date  '+[%Y-%m-%d %H:%M:%S]'` "BEGIN EXPLAIN ALL TPCH PLAN"
   for i in {1..22}
   do
      sql_explain="source explain_mysql/${i}.sql"
      echo `date  '+[%Y-%m-%d %H:%M:%S]'` "BEGIN EXPLAIN Q${i}:"
      echo ${sql_explain} | ${TPCH_TEST} | sed 's/\\n/\n/g' |tee explain_log/${i}.exp
      echo `date  '+[%Y-%m-%d %H:%M:%S]'` "Q${i} END"
   done
   }

   function do_warmup
   {
   #warmup预热
   totaltime=0
   for i in {1..22}
   do
         starttime=`date +%s%N`
         echo `date  '+[%Y-%m-%d %H:%M:%S]'` "BEGIN prewarm Q${i}"
         sql1="source mysql_sql/${i}.sql"
         echo ${sql1}| ${TPCH_TEST} > mysql_log/${i}_prewarm.log  || ret=1
         stoptime=`date +%s%N`
         costtime=`echo ${stoptime} ${starttime} | awk '{printf "%0.2f\n", ($1 - $2) / 1000000000}'`
         first_array[$i]=$(echo "scale=2; ${first_array[$i]} + $costtime" | bc)  
         echo `date  '+[%Y-%m-%d %H:%M:%S]'` "END,COST ${costtime}s"
         totaltime=`echo ${totaltime} ${costtime} | awk '{printf "%0.2f\n", ($1 + $2)}'`
   done
   echo "total cost:${totaltime}s"
   }

   function hot_run
   {
   #正式执行
   for j in {1..10}
   do
   totaltime=0
   for i in {1..22}
   do
         starttime=`date +%s%N`
         echo `date  '+[%Y-%m-%d %H:%M:%S]'` "BEGIN BEST Q${i} (hot run)"
         sql1="source mysql_sql/${i}.sql"
         echo ${sql1}| ${TPCH_TEST} > mysql_log/${i}.log  || ret=1
         stoptime=`date +%s%N`
         costtime=`echo ${stoptime} ${starttime} | awk '{printf "%0.2f\n", ($1 - $2) / 1000000000}'`
         hot_array[$i]=$(echo "scale=2; ${hot_array[$i]} + $costtime" | bc)  
         echo `date  '+[%Y-%m-%d %H:%M:%S]'` "END,COST ${costtime}s"
         totaltime=`echo ${totaltime} ${costtime} | awk '{printf "%0.2f\n", ($1 + $2)}'`
   done
   echo "total cost:${totaltime}s"
   done
   }

   function cold_run
   {
   #正式执行
   for j in {1..3}
   do
   totaltime=0
   for i in {1..22}
   do
         clear_kvcache
         starttime=`date +%s%N`
         echo `date  '+[%Y-%m-%d %H:%M:%S]'` "BEGIN BEST Q${i} (cold run)"
         sql1="source mysql_sql/${i}.sql"
         echo $sql1| $TPCH_TEST > mysql_log/${i}_cold.log  || ret=1
         stoptime=`date +%s%N`
         costtime=`echo $stoptime $starttime | awk '{printf "%0.2f\n", ($1 - $2) / 1000000000}'`
         cold_array[$i]=$(echo "scale=2; ${cold_array[$i]} + $costtime" | bc)
         echo `date  '+[%Y-%m-%d %H:%M:%S]'` "END,COST ${costtime}s"
         totaltime=`echo ${totaltime} ${costtime} | awk '{printf "%0.2f\n", ($1 + $2)}'`
   done
   echo "total cost:${totaltime}s"
   done
   }

   do_explain

   do_warmup

   hot_run

   cold_run

   ```
 2. 执行测试脚本。

   ```bash
   sh tpch.sh

   ```

### FAQ

- 导入数据失败。报错信息如下：

  ```bash
  ERROR 1017 (HY000) at line 1: File not exist

  ```

  `tbl` 文件必须放在所连接的 OceanBase 数据库所在机器的某个目录下，因为加载数据必须本地导入。
 - 查看数据报错。报错信息如下：

  ```bash
  ERROR 4624 (HY000)：No memory or reach tenant memory limit

  ```

  内存不足，建议增大租户内存。
 - 导入数据报错。报错信息如下：

  ```bash
  ERROR 1227 (42501) at line 1: Access denied

  ```

  需要授予用户访问权限。运行以下命令，授予权限：

  ```bash
  grant file on *.* to tpch_100g_part;

  ```

 上一篇 下一篇 ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
