暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

TiDB实践—索引加速+分布式执行框架创建索引提升70+倍

背景介绍

TiDB 采用在线异步变更的方式执行 DDL 语句,从而实现 DDL 语句的执行不会阻塞其他会话中的 DML 语句。按照是否需要操作 DDL 目标对象所包括的数据来划分,DDL 语句可以划分为 逻辑 DDL 语句物理 DDL 语句。逻辑 DDL 语句通常只修改数据库对象的元数据,不对变更对象存储的数据进行处理,例如变更表名或变更列名。物理 DDL 语句不但会修改变更对象的元数据,同时也修改变更对象所存储的用户数据,例如,为表创建索引,不仅需要变更表的定义,同时也需要做一次全表扫描以构建新增加的索引。

在 TiDB 中,物理 DDL 被称为 Reorg DDL(Reorg 即 Reorganization)。目前物理 DDL 只包含 ADD INDEX
以及有损列类型变更(例如从 INT
转成 CHAR
类型)这两种类型。物理 DDL 的特点是执行时间较长,且执行时间与表的数据量、机器配置以及业务负载有关。

为了优化 TiDB 中物理 DDL 性能,TiDB v6.3.0 支持开启添加索引加速功能,提升了创建索引回填过程的速度。从 v7.1.0 开始,TiDB 又引入了分布式执行框架,以进一步发挥分布式架构的资源优势。该框架的目标是对基于该框架的任务进行统一调度与分布式执行,并提供整体和单个任务两个维度的资源管理能力,更好地满足用户对于资源使用的预期。

基于以上信息,使用创建索引为例,在测试环境中验证 TiDB 索引加速及分布式执行框架对物理 DDL 的性能提升情况,供读者参考。

先上结论

  1. 基于 10 亿 表创建索引,采用普通 Online DDL 方式,耗时约 12 小时 21 分钟

  2. 基于 10 亿 表创建索引,采用 Fast DDL 方式,耗时约 30 分钟,比普通 DDL 提升约 24

  3. 基于 10 亿 表创建索引,采用 Fast DDL + 分布式框架

    1. 在 3 个 TiDB Server 时,耗时约 10 分钟,是 Fast DDL 性能的 3 倍,是普通 DDL 的 72

    2. 在 2 个 TiDB Server 时,耗时约 14~15 分钟,是 Fast DDL 性能的 2 倍,是普通 DDL 的 48

    3. 证明采用分布式框架性能基本随着 TiDB Server 个数增长呈准线性增长

创建索引方式

参数设置

平均耗时

普通 Online DDL

SET GLOBAL tidb_ddl_enable_fast_reorg = OFF;

12小时21分钟

Fast DDL

SET GLOBAL tidb_ddl_enable_fast_reorg = ON; 

SET GLOBAL tidb_enable_dist_task = OFF;

30 分钟

Fast DDL + 分布式框架

SET GLOBAL tidb_ddl_enable_fast_reorg = ON; 

SET GLOBAL tidb_enable_dist_task = ON;

10 分钟

环境准备

  • 节点配置(3节点 ARM 机器)

IP

配置

磁盘

基础平台

10.x.x.1

64C 128G

2.5 T

ARM

10.x.x.2

64C 128G

2.5 T

ARM

10.x.x.3

64C 128G

2.5 T

ARM

  • 集群信息(V 7.5.1 版本,混合部署)

    [tidb@host-10-x-x-1 ~]$ tiup cluster display tidb-free
    tiup is checking updates for component cluster ...
    Starting component `cluster`: home/tidb/.tiup/components/cluster/v1.14.1/tiup-cluster display tidb-free
    Cluster type: tidb
    Cluster name: tidb-free
    Cluster version: v7.5.1
    Deploy user: tidb
    SSH type: builtin
    Dashboard URL: http://10.x.x.2:2379/dashboard
    Grafana URL: http://10.x.x.1:3000
    ID Role Host Ports OS/Arch Status Data Dir Deploy Dir
    -- ---- ---- ----- ------- ------ -------- ----------
    10.x.x.1:9093 alertmanager 10.x.x.1 9093/9094 linux/aarch64 Up data1/tidb-data/alertmanager-9093 data1/tidb-deploy/alertmanager-9093
    10.x.x.1:3000 grafana 10.x.x.1 3000 linux/aarch64 Up - data1/tidb-deploy/grafana-3000
    10.x.x.1:2379 pd 10.x.x.1 2379/2380 linux/aarch64 Up|L data1/tidb-data/pd-2379 data1/tidb-deploy/pd-2379
    10.x.x.2:2379 pd 10.x.x.2 2379/2380 linux/aarch64 Up|UI data1/tidb-data/pd-2379 data1/tidb-deploy/pd-2379
    10.x.x.3:2379 pd 10.x.x.3 2379/2380 linux/aarch64 Up data1/tidb-data/pd-2379 data1/tidb-deploy/pd-2379
    10.x.x.1:9095 prometheus 10.x.x.1 9095/12020 linux/aarch64 Up data1/tidb-data/prometheus-9095 data1/tidb-deploy/prometheus-9095
    10.x.x.1:4000 tidb 10.x.x.1 4000/10080 linux/aarch64 Up - data1/tidb-deploy/tidb-4000
    10.x.x.2:4000 tidb 10.x.x.2 4000/10080 linux/aarch64 Up - /data1/tidb-deploy/tidb-4000
    10.x.x.3:4000 tidb 10.x.x.3 4000/10080 linux/aarch64 Up - /data1/tidb-deploy/tidb-4000
    10.x.x.1:20160 tikv 10.x.x.1 20160/20180 linux/aarch64 Up /data1/tidb-data/tikv-20160 /data1/tidb-deploy/tikv-20160
    10.x.x.2:20160 tikv 10.x.x.2 20160/20180 linux/aarch64 Up /data1/tidb-data/tikv-20160 /data1/tidb-deploy/tikv-20160
    10.x.x.3:20160 tikv 10.x.x.3 20160/20180 linux/aarch64 Up /data1/tidb-data/tikv-20160 /data1/tidb-deploy/tikv-20160


    mysql> select version();
    +--------------------+
    | version() |
    +--------------------+
    | 8.0.11-TiDB-v7.5.1 |
    +--------------------+
    1 row in set (0.00 sec)
    • 参数配置

      tiup cluster show-config tidb-test


      ·····


      server_configs:
      tidb:
      temp-dir: /data1/tidb-free-temp
      tikv:
      storage.block-cache.capacity: 10240MiB

      ·····
      • 数据准备

        wget https://github.com/akopytov/sysbench/archive/refs/tags/1.0.20.tar.gz
        tar -zxvf 1.0.20.tar.gz
        cd sysbench-1.0.20
        ./autogen.sh
        ./configure
        make && make install


        [root@vm172-16-201-99 /home/tidb/zcy/sysbench-1.0.20]# sysbench --version
        sysbench 1.0.20




        vi config
        mysql-host=172.16.201.159
        mysql-port=4099
        mysql-user=root
        mysql-password=zcy@root
        mysql-db=sbtest
        time=600
        threads=16
        report-interval=10
        db-driver=mysql


        sysbench --config-file=config oltp_point_select --tables=1 --table-size=1000000000 prepare

        测试过程

          mysql> show create table sbtest1;
          +---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
          | Table | Create Table |
          +---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
          | sbtest1 | CREATE TABLE `sbtest1` (
          `id` int(11) NOT NULL AUTO_INCREMENT,
          `k` int(11) NOT NULL DEFAULT '0',
          `c` char(120) NOT NULL DEFAULT '',
          `pad` char(60) NOT NULL DEFAULT '',
          PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=45086776 |
          +---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
          1 row in set (0.02 sec)




          mysql> select count(*) from sbtest1;
          +------------+
          | count(*) |
          +------------+
          | 1000000000 |
          +------------+
          1 row in set (1 min 30.40 sec)


          测试1: Online DDL

            SET GLOBAL tidb_ddl_enable_fast_reorg = OFF
            create index k_1 on sbtest1(k);
            • 测试输出:

              mysql> admin show ddl jobs;
              +--------+---------+-------------------------+---------------------+--------------+-----------+----------+------------+---------------------+---------------------+---------------------+--------+
              | JOB_ID | DB_NAME | TABLE_NAME | JOB_TYPE | SCHEMA_STATE | SCHEMA_ID | TABLE_ID | ROW_COUNT | CREATE_TIME | START_TIME | END_TIME | STATE |
              +--------+---------+-------------------------+---------------------+--------------+-----------+----------+------------+---------------------+---------------------+---------------------+--------+
              | 106 | sbtest | sbtest1 | add index /* txn */ | public | 102 | 104 | 1000000000 | 2024-07-16 09:40:36 | 2024-07-16 09:40:36 | 2024-07-16 22:01:38 | synced |
              +--------+---------+-------------------------+---------------------+--------------+-----------+----------+------------+---------------------+---------------------+---------------------+--------+
              10 rows in set (0.01 sec)
              • 执行耗时:44463 秒 = 12 小时 21 分钟 3 秒

              • 资源截图:

              测试2: Fast Online DDL

                SET GLOBAL tidb_ddl_enable_fast_reorg = ON
                SET GLOBAL tidb_enable_dist_task = OFF;
                create index k_1 on sbtest1(k);
                • 测试输出:

                  mysql> admin show ddl jobs;
                  +--------+---------+---------------------+---------------------------+--------------+-----------+----------+------------+---------------------+---------------------+---------------------+---------------+
                  | JOB_ID | DB_NAME | TABLE_NAME | JOB_TYPE | SCHEMA_STATE | SCHEMA_ID | TABLE_ID | ROW_COUNT | CREATE_TIME | START_TIME | END_TIME | STATE |
                  +--------+---------+---------------------+---------------------------+--------------+-----------+----------+------------+---------------------+---------------------+---------------------+---------------+
                  | 112 | sbtest | sbtest1 | add index /* ingest */ | public | 102 | 104 | 1000000000 | 2024-07-16 23:37:42 | 2024-07-16 23:37:42 | 2024-07-17 00:07:52 | synced |
                  +--------+---------+---------------------+---------------------------+--------------+-----------+----------+------------+---------------------+---------------------+---------------------+---------------+
                  10 rows in set (0.01 sec)
                  • 执行耗时:1812 秒 = 30 分钟 12 秒

                  • 资源截图:

                  测试3: 分布式执行框架 Fast Online DDL

                  使用 3 个 TiDB Server 测试

                    SET GLOBAL tidb_ddl_enable_fast_reorg = ON
                    SET GLOBAL tidb_enable_dist_task = ON;
                    --以下可选
                    TiDB-server-1: SET GLOBAL tidb_service_scope = 'background'
                    TiDB-server-2: SET GLOBAL tidb_service_scope = 'background'
                    TiDB-server-3: SET GLOBAL tidb_service_scope = 'background'
                    等同于
                    SET GLOBAL tidb_service_scope = ''


                    create index k_1 on sbtest1(k);
                    • 测试输出:

                      mysql> admin show ddl jobs;
                      +--------+---------+------------+---------------------------+--------------+-----------+----------+------------+---------------------+---------------------+---------------------+---------------+
                      | JOB_ID | DB_NAME | TABLE_NAME | JOB_TYPE | SCHEMA_STATE | SCHEMA_ID | TABLE_ID | ROW_COUNT | CREATE_TIME | START_TIME | END_TIME | STATE |
                      +--------+---------+------------+---------------------------+--------------+-----------+----------+------------+---------------------+---------------------+---------------------+---------------+
                      | 118 | sbtest | sbtest1 | add index /* ingest */ | public | 102 | 104 | 671304000 | 2024-07-17 09:55:09 | 2024-07-17 09:55:09 | 2024-07-17 10:05:25 | synced |
                      +--------+---------+------------+---------------------------+--------------+-----------+----------+------------+---------------------+---------------------+---------------------+---------------+
                      • 执行耗时:

                      第1次

                      654 秒

                      第2次

                      618 秒

                      第3次

                      591 秒

                      第4次

                      606 秒

                      第5次

                      634 秒

                      平均值

                      620 秒

                      • 资源截图:

                      使用 2 个 TiDB Server 测试

                        SET GLOBAL tidb_ddl_enable_fast_reorg = ON
                        SET GLOBAL tidb_enable_dist_task = ON;


                        TiDB-server-2: SET GLOBAL tidb_service_scope = 'background'
                        TiDB-server-3: SET GLOBAL tidb_service_scope = 'background'


                        create index k_1 on sbtest1(k);
                        • 测试输出:

                          mysql> admin show ddl jobs;
                          +--------+---------+------------+------------------------+--------------+-----------+----------+-----------+---------------------+---------------------+---------------------+--------+
                          | JOB_ID | DB_NAME | TABLE_NAME | JOB_TYPE | SCHEMA_STATE | SCHEMA_ID | TABLE_ID | ROW_COUNT | CREATE_TIME | START_TIME | END_TIME | STATE |
                          +--------+---------+------------+------------------------+--------------+-----------+----------+-----------+---------------------+---------------------+---------------------+--------+
                          |    126 | sbtest  | sbtest1    | add index /* ingest */ | public       |       102 |      104 | 868990050 | 2024-07-17 14:16:18 | 2024-07-17 14:16:18 | 2024-07-17 14:30:20 | synced |
                          • 执行耗时:

                          第一次

                          843 秒

                          第二次

                          879 秒

                          第三次

                          876 秒

                          第四次

                          816 秒

                          第五次

                          903 秒

                          平均值

                          863 秒

                          • 资源截图:

                          参数说明

                          tidb_ddl_enable_fast_reorg
                           从 v6.3.0 版本开始引入

                          • 作用域:GLOBAL

                          • 是否持久化到集群:是

                          • 是否受 Hint SET_VAR 控制:否

                          • 类型:布尔型

                          • 默认值:ON

                          • 这个变量用来控制是否开启添加索引加速功能,来提升创建索引回填过程的速度。开启该变量对于数据量较大的表有一定的性能提升。

                          • TiDB v7.1.0 引入了快速加索引功能的检查点机制,即使 TiDB owner 因故障重启或者切换,也能够通过自动定期保存的检查点恢复部分进度。

                          • 要验证已经完成的 ADD INDEX
                             操作是否使用了添加索引加速功能,可以执行 ADMIN SHOW DDL JOBS
                             语句查看 JOB_TYPE
                             一列中是否含有 ingest
                             字样。

                          tidb_enable_dist_task
                           从 v7.1.0 版本开始引入

                          • 作用域:GLOBAL

                          • 是否持久化到集群:是

                          • 是否受 Hint SET_VAR 控制:否

                          • 默认值:ON

                          • 这个变量用于控制是否开启 TiDB 分布式执行框架。开启分布式执行框架后,DDL 和 Import 等将会由集群中多个 TiDB 节点共同完成。

                          • 从 TiDB v7.1.0 开始,支持分布式执行分区表的 ADD INDEX

                          • 从 TiDB v7.2.0 开始,支持分布式导入任务 IMPORT INTO

                          • 从 TiDB v8.1.0 开始,该变量默认开启。如果要从低版本的集群升级到 v8.1.0 或更高版本,且该集群已开启分布式执行框架,为了避免升级期间 ADD INDEX
                             操作可能导致数据索引不一致的问题,请在升级前关闭分布式执行框架(即将 tidb_enable_dist_task
                             设置为 OFF
                            ),升级后再手动开启。

                          • 该变量由 tidb_ddl_distribute_reorg
                             改名而来。

                          tidb_service_scope
                           从 v7.4.0 版本开始引入

                          • 作用域:GLOBAL

                          • 是否持久化到集群:否

                          • 是否受 Hint SET_VAR 控制:否

                          • 类型:字符串

                          • 默认值:""

                          • 可选值:"" 或 background

                          • 该变量是一个实例级别的变量,用于控制 TiDB 分布式执行框架 下各 TiDB 节点的服务范围。当设置 TiDB 节点的 tidb_service_scope
                             为 background
                             时,分布式执行框架将调度该节点执行任务(如 ADD INDEX
                             和 IMPORT INTO
                            )。

                          参考链接

                          TiDB DDL 执行原理及最佳实践:https://docs.pingcap.com/zh/tidb/stable/ddl-introduction

                          TiDB 分布式执行框架:https://docs.pingcap.com/zh/tidb/stable/tidb-distributed-execution-framework

                          文章转载自数据源的技术后花园,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                          评论