---
title: OceanBase 数据库 V4.x 版本中 sql_audit 视图中 partition_cnt 统计方式的变化-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于OceanBase 数据库 V4.x 版本中 sql_audit 视图中 partition_cnt 统计方式的变化相关的常见问题和使用技巧，帮助您快速解决OceanBase 数据库 V4.x 版本中 sql_audit 视图中 partition_cnt 统计方式的变化的难题。
---
切换语言

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

划线反馈

# OceanBase 数据库 V4.x 版本中 sql_audit 视图中 partition_cnt 统计方式的变化

更新时间：2026-05-25 09:11

适用版本： V2.1.x、V2.2.x、V3.1.x、V3.2.x、V4.0.x、V4.1.x、V4.2.x 内容类型：TechNote  

在 POC 性能调优测试 和 日常生产环境监控时，经常需要关注单条 SQL 访问的分区数量（对应 OceanBase 数据库 V2.x/V3.x 中 `gv$sql_audit` 视图和 OceanBase 数据库 V4.x 中 `gv$ob_sql_audit` 视图中的 `partition_cnt` 字段）。OLTP 业务中对于访问 `Partition` 数量大于 1 的 SQL 尤其需要警惕：如果访问分区数不符合预期，往往意味着执行计划发生了走偏。

本文主要描述不同 OceanBase 数据库版本的内部审计视图（`gv$sql_audit` 或 `gv$ob_sql_audit`）统计 `partiton_cnt` 方式的差异。

OceanBase 数据库 V4.x 版本中引入了 Tablet 的概念，建立了用户表分区到 Tablet 的映射，实现底层数据存储与 schema 元数据的解耦：用户创建的一个分区对应一个 Tablet，表(table)、分区 (Partition) 作为用户创建的逻辑对象，而 Tablet 作为实际承载数据的物理存储单位。Tablet 和 Partition 的概念有所不同，Partition 表示 Table 的一个数据分片，在一个 Partition 中除了包含主表数据之外，还包含对应的局部索引。一个 Partition 中可能包含一个或者多个 Tablet，例如 Partition 的一个局部索引就会对应一个 Tablet，同一个 Partition 的所有 Tablet 会强制绑定在一起，保证它们存储在一台机器上。适应这种变化，OceanBase 数据库内核在统计一条 SQL 访问的 `partition_cnt` 的方式也略有不同：对于 `gv$ob_sql_audit` 中的 `partition_cnt` 字段，在 OceanBase 数据库 V4.x 版本中不同的 Tablet 也都统计到里面了，即 OceanBase 数据库 V4.x 版本中的主表和局部索引表，现在都各自算一个 Partition，因此访问单个分区时，如果走了二级局部索引回表，则 `partition_cnt=2`；而在 OceanBase 数据库 V2.x/V3.x 版本中执行同样的 SQL 时， `partition_cnt` 则不会统计局部索引（`partition_cnt=1`）。

示例如下。

1. 创建表 t1。

   ```shell
   MySQL [test]> create table t1 (id int primary key, value int, name varchar(100));
   Query OK, 0 rows affected (0.091 sec)

   ```
 2. 向 t1 表插入数据。

   ```shell
   MySQL [test]> insert into t1 values (1,1,'a'),(2,2,'b'),(3,3,'c'),(4,4,'d'),(5,5,'e');
   Query OK, 5 rows affected (0.011 sec)
   Records: 5  Duplicates: 0  Warnings: 0

   ```
 3. 创建索引 idx1 。

   ```shell
   MySQL [test]> create index idx1 on t1(value);
   Query OK, 0 rows affected (0.506 sec)

   ```
 4. 执行如下查询语句。

   ```shell
   MySQL [test]> select * from t1 where value=3;

   ```

   输出结果如下：

   ```shell
   +----+-------+------+
   | id | value | name |
   +----+-------+------+
   |  3 |     3 | c    |
   +----+-------+------+
   1 row in set (0.036 sec)

   ```
 5. 展示执行计划。

   ```shell
   MySQL [test]> explain select * from t1 where value=3;   -- 先走二级局部索引，再回表

   ```

   输出结果如下：

   ```shell
   +----------------------------------------------------------------------+
   | Query Plan                                                           |
   +----------------------------------------------------------------------+
   | =========================================================            |
   | |ID|OPERATOR             |NAME    |EST.ROWS|EST.TIME(us)|            |
   | ---------------------------------------------------------            |
   | |0 |EXCHANGE IN REMOTE   |        |1       |10          |            |
   | |1 |└─EXCHANGE OUT REMOTE|        |1       |9           |            |
   | |2 |  └─TABLE RANGE SCAN |t1(idx1)|1       |7           |            |
   | =========================================================            |
   | Outputs & filters:                                                   |
   | -------------------------------------                                |
   |   0 - output([t1.id], [t1.value], [t1.name]), filter(nil)            |
   |   1 - output([t1.id], [t1.value], [t1.name]), filter(nil)            |
   |   2 - output([t1.id], [t1.value], [t1.name]), filter(nil), rowset=16 |
   |       access([t1.id], [t1.value], [t1.name]), partitions(p0)         |
   |       is_index_back=true, is_global_index=false,                     |
   |       range_key([t1.value], [t1.id]), range(3,MIN ; 3,MAX),          |
   |       range_cond([t1.value = 3])                                     |
   +----------------------------------------------------------------------+
   16 rows in set (0.004 sec)

   ```
 6. 执行如下查询语句。

   ```shell
   MySQL [test]> select * from t1 where id=3;

   ```

   输出结果如下：

   ```shell
   +----+-------+------+
   | id | value | name |
   +----+-------+------+
   |  3 |     3 | c    |
   +----+-------+------+
   1 row in set (0.004 sec)

   ```
 7. 展示执行计划。

   ```shell
   MySQL [test]> explain select * from t1 where id=3;   -- 走主键索引，无需回表

   ```

   输出结果如下：

   ```shell
   +----------------------------------------------------------------------+
   | Query Plan                                                           |
   +----------------------------------------------------------------------+
   | =====================================================                |
   | |ID|OPERATOR             |NAME|EST.ROWS|EST.TIME(us)|                |
   | -----------------------------------------------------                |
   | |0 |EXCHANGE IN REMOTE   |    |1       |8           |                |
   | |1 |└─EXCHANGE OUT REMOTE|    |1       |7           |                |
   | |2 |  └─TABLE GET        |t1  |1       |5           |                |
   | =====================================================                |
   | Outputs & filters:                                                   |
   | -------------------------------------                                |
   |   0 - output([t1.id], [t1.value], [t1.name]), filter(nil)            |
   |   1 - output([t1.id], [t1.value], [t1.name]), filter(nil)            |
   |   2 - output([t1.id], [t1.value], [t1.name]), filter(nil), rowset=16 |
   |       access([t1.id], [t1.value], [t1.name]), partitions(p0)         |
   |       is_index_back=false, is_global_index=false,                    |
   |       range_key([t1.id]), range[3 ; 3],                              |
   |       range_cond([t1.id = 3])                                        |
   +----------------------------------------------------------------------+
   16 rows in set (0.003 sec)

   ```
 8. 通过 gv$ob_sql_audit 视图中的字段 query_sql（实际的 SQL 语句）获取 partition_cnt（请求涉及的分区数）值。

   ```shell
   ## -- 在 OceanBase 数据库 V3.2.4 版本中
   MySQL [oceanbase]> select query_sql,partition_cnt from gv$sql_audit where tenant_id=1001 and query_sql like 'select * from t1%';

   ```

   输出结果如下：

   ```shell
   +--------------------------------+---------------+
   | query_sql                      | partition_cnt |
   +--------------------------------+---------------+
   | select * from t1 where value=3 |             1 |   <== 走的是二级局部索引TABLE SCAN|t1(idx1)
   | select * from t1 where id=3    |             1 |   <== 走的是主键索引TABLE GET|t1
   +--------------------------------+---------------+
   2 rows in set (0.15 sec)

   ```
 9. 向 t1 表插入数据。

   ```shell
   MySQL [test]> insert into t1 values (1,1,'a'),(2,2,'b'),(3,3,'c'),(4,4,'d'),(5,5,'e');
   Query OK, 5 rows affected (0.005 sec)
   Records: 5  Duplicates: 0  Warnings: 0

   ```

   ```shell
   MySQL [test]> insert into t1 values(6,6,'f');
   Query OK, 1 row affected (0.003 sec)

   ```
 10. 通过 gv$ob_sql_audit 视图中的字段 query_sql（实际的 SQL 语句）获取 partition_cnt（请求涉及的分区数）值。

    ```shell
    MySQL [oceanbase]> select query_sql,partition_cnt from gv$ob_sql_audit where tenant_id=1002 and query_sql like 'insert into t1 values%';

    ```

    输出结果如下：

    ```shell
    +-------------------------------------------------------------------------+---------------+
    | query_sql                                                               | partition_cnt |
    +-------------------------------------------------------------------------+---------------+
    | insert into t1 values (1,1,'a'),(2,2,'b'),(3,3,'c'),(4,4,'d'),(5,5,'e') |             2 |
    | insert into t1 values(6,6,'f')                                          |             2 |
    +-------------------------------------------------------------------------+---------------+
    2 rows in set (1.328 sec)

    ```

    ```shell
    MySQL [oceanbase]> select query_sql,partition_cnt from gv$sql_audit where tenant_id=1001 and query_sql like 'insert into t1 values%';

    ```

    输出结果如下：

    ```shell
    +-------------------------------------------------------------------------+---------------+
    | query_sql                                                               | partition_cnt |
    +-------------------------------------------------------------------------+---------------+
    | insert into t1 values (1,1,'a'),(2,2,'b'),(3,3,'c'),(4,4,'d'),(5,5,'e') |             1 |
    | insert into t1 values(6,6,'f')                                          |             1 |
    +-------------------------------------------------------------------------+---------------+
    2 rows in set (0.14 sec)

    ```

    #### 注意

    一个表上如果有 10 个局部索引，针对单行的插入，V3.x 版本中会记录一个分区，而在 V4.x 版本中则会记录 11 个分区。
 11. 通过 gv$ob_sql_audit 视图中的字段 query_sql（实际的 SQL 语句）获取 partition_cnt（请求涉及的分区数）值。

    ```shell
    ## -- 在 OceanBase 数据库 V4.x 版本中
    MySQL [oceanbase]> select query_sql,partition_cnt from gv$ob_sql_audit where tenant_id=1002 and query_sql like 'select * from t1%';

    ```

    输出结果如下：

    ```shell
    +--------------------------------+---------------+
    | query_sql                      | partition_cnt |
    +--------------------------------+---------------+
    | select * from t1 where value=3 |             2 |   <== 先走二级局部索引，再回表
    | select * from t1 where id=3    |             1 |   <== 走主键索引，无需回表
    +--------------------------------+---------------+
    2 rows in set (1.338 sec)

    ```

    #### 说明

    对于上述同样的 SQL 查询，OceanBase 数据库 V4.x 版本中实际的数据库执行成本 COST 应该跟原来差不多，只是 `partition_cnt` 统计方式上的变化。

## 适用版本

OceanBase 数据库 V2.x、V3.x、V4.x 版本。

上一篇

[OceanBase 数据库各个版本中参数和变量相关的系统视图](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000001048086)

下一篇

[为什么 gv$plan_cache_plan_stat 里的 SLOWEST_EXE_USEC 记录不准确](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000004409029) ![有帮助](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) 咨询热线
