---
title: GROUP BY / DISTINCT 跳跃式去重扫描场景问题排查-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于GROUP BY / DISTINCT 跳跃式去重扫描场景问题排查相关的常见问题和使用技巧，帮助您快速解决GROUP BY / DISTINCT 跳跃式去重扫描场景问题排查的难题。
image: https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*OSPzQ6GUQF4AAAAAQHAAAAgAeiGDAQ/original
---
切换语言

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

划线反馈

# GROUP BY / DISTINCT 跳跃式去重扫描场景问题排查

更新时间：2026-08-21 03:56

适用版本： V4.4.x、V4.3.x、V4.2.x、V4.1.x、V4.0.x、V3.3.x、V3.2.x、V3.1.x、V2.2.x、V2.1.x、V1.4.x 内容类型：Troubleshoot  

## 问题现象

用户在对比 OceanBase 和 MySQL 的 SQL 执行效率时，发现对于无过滤条件的 `GROUP BY` 查询，OceanBase 的执行时间显著长于 MySQL。具体表现为 OceanBase 执行耗时约 0.8 秒，而 MySQL 只需 0.04 秒左右，尽管两环境的表数据量相同。

OceanBase 执行计划如下：

```sql
obclient> select dbms_xplan.display_cursor(0,'all')\G;
*************************** 1. row ***************************
dbms_xplan.display_cursor(0,'all'): ================================================================================================================================================
|ID|OPERATOR         |NAME                                              |EST.ROWS|EST.TIME(us)|REAL.ROWS|REAL.TIME(us)|IO TIME(us)|CPU TIME(us)|
------------------------------------------------------------------------------------------------------------------------------------------------
|0 |MERGE DISTINCT   |                                                  |120     |365475      |54       |804492       |0          |698457      |
|1 |└─TABLE FULL SCAN|tbl_x1(idx_tbl_x1_5)                              |21653574|106216      |21653574 |804492       |0          |105363      |
================================================================================================================================================
is_index_back=false, is_global_index=false, range(MIN,MIN,MIN ; MAX,MAX,MAX)always true

Used Hint:
-------------------------------------
  tbl_x1:
      table_rows:21190271
      physical_range_rows:21653574
      logical_range_rows:21653574
      output_rows:21653574
      table_dop:1

```

查询语句为：

```sql
SELECT c11 AS label, c16 AS sonLabel
FROM tbl_x1
GROUP BY c11, c16;

```

表结构如下：

```sql
CREATE TABLE `tbl_x1` (
  `c01` char(32) NOT NULL,
  `c02` char(32) NOT NULL,
  `c03` varchar(20) DEFAULT NULL,
  `c04` varchar(20) DEFAULT NULL,
  `c05` varchar(11) DEFAULT NULL,
  `c06` varchar(11) DEFAULT NULL,
  `c07` timestamp(3) NULL DEFAULT NULL,
  `c08` timestamp(3) NULL DEFAULT NULL,
  `c09` char(8) DEFAULT NULL,
  `c10` tinyint(4) DEFAULT NULL,
  `c11` char(2) DEFAULT NULL,
  `c12` varchar(64) DEFAULT NULL,
  `c13` mediumtext DEFAULT NULL,
  `c14` varchar(256) DEFAULT NULL,
  `c15` varchar(60) DEFAULT NULL,
  `c16` varchar(6) DEFAULT NULL,
  `c17` mediumtext DEFAULT NULL,
  `c18` char(32) DEFAULT NULL,
  `c19` timestamp(3) NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  `c20` char(32) DEFAULT NULL,
  `c21` timestamp(3) NULL DEFAULT CURRENT_TIMESTAMP(3),
  `c22` tinyint(4) DEFAULT '0',
  `c23` char(32) DEFAULT NULL,
  `c24` tinyint(4) DEFAULT NULL,
  `c25` mediumtext DEFAULT NULL,
  `c26` varchar(45) DEFAULT NULL,
  `c27` varchar(45) DEFAULT NULL,
  `c28` char(32) DEFAULT NULL,
  `c29` int(11) DEFAULT '0',
  PRIMARY KEY (`c01`),
  KEY `idx_tbl_x1_1` (`c02`, `c12`) BLOCK_SIZE 16384 LOCAL,
  KEY `idx_tbl_x1_2` (`c28`) BLOCK_SIZE 16384 LOCAL,
  KEY `idx_tbl_x1_4` (`c21`, `c05`, `c28`) BLOCK_SIZE 16384 LOCAL,
  KEY `idx_tbl_x1_5` (`c11`, `c16`) BLOCK_SIZE 16384 LOCAL,
  KEY `idx_tbl_x1_6` (`c14`, `c22`) BLOCK_SIZE 16384 LOCAL,
  KEY `idx_tbl_x1_7` (`c26`) BLOCK_SIZE 16384 LOCAL
) ORGANIZATION INDEX DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC
  COMPRESSION='zstd_1.3.8' REPLICA_NUM=2 BLOCK_SIZE=16384
  USE_BLOOM_FILTER=FALSE ENABLE_MACRO_BLOCK_BLOOM_FILTER=FALSE
  TABLET_SIZE=134217728 PCTFREE=0;

```

MySQL 的执行计划显示使用了 `Using index for group-by` 优化。

## 问题原因

此问题是 OceanBase 当前的设计行为（By Design）。

- OceanBase 目前仅支持 `GROUP BY` 单个普通列且不带聚合函数的场景下压至存储层。
 - 对于 `GROUP BY` 多个普通列的情况，OceanBase 不支持将其下压到存储层，在没有特殊优化的情况下，等同于对索引表进行全表扫描，从而增加了执行时间。
 - 相比之下，MySQL 8.0 使用了 Loose Index Scan（跳跃式索引扫描）技术。当查询可以利用组合索引的前缀部分进行分组时，MySQL 能够通过跳跃到下一组唯一前缀的方式，只扫描每组的第一行，从而显著减少需要扫描的行数，提高查询效率。

## 关键信息

- 问题 SQL 的语义是获取 `(c11, c16)` 列组合的去重集合，可以等价改写为使用 `DISTINCT`：

```sql
SELECT DISTINCT c11 AS label, c16 AS sonLabel
FROM tbl_x1;

```

- 在 MySQL 中，该语句可以利用索引 `idx_tbl_x1_5 (c11, c16)` 的有序性，通过跳跃式扫描，只取每组的首行，执行计划中 `Extra` 列会显示 `Using index for group-by`。
 - 跳跃式扫描的特点是扫描行数少，但会产生更多的随机 IO。这种优化适用于分组列基数（NDV）较小、数据分布稀疏的场景。在本案例中，用户表行数为 21,190,271，`c11` 的 NDV 为 12，`c16` 的 NDV 为 10，分组数较少，非常适合跳跃式扫描优化。

## 问题的风险及影响

- SQL 执行效率低下，在高并发场景下可能引起系统响应延迟增加。

## 适用版本

所有版本。

## 解决方法

1. **临时缓解**：增加 SQL 执行的并行度，以提高查询效率。

## 规避方式

对于需要频繁执行 `GROUP BY` 多个普通列的查询，建议通过增加并行度的方式提升查询性能。

上一篇

[dbms_xplan.display_active_session_plan 记录的 real_time 实时时间不准确问题](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000006896960)

下一篇

[开启 insertup GTS 优化后并发更新场景误报错误码 4377](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000006868405) ![有帮助](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) 咨询热线
