---
title: "使用 Query Block Name 和 QB_NAME Hint 控制查询优化 - OceanBase 数据库 V4.6.0 | OceanBase 文档中心"
description: 使用 Query Block Name 和 QB_NAME Hint 控制查询优化 OceanBase 数据库的优化器对查询进行分析处理时，会根据查询的结构分解为多个查询块（Query Block），每个块拥有唯一的查询块名（Query Block Name，简称 QB Name）。如果不手动指定，优化器则自动生成 …
---
切换语言

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

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

# 使用 Query Block Name 和 QB_NAME Hint 控制查询优化

更新时间：2026-07-05 14:35:07

[编辑](https://github.com/oceanbase/oceanbase-doc/edit/V4.6.0/zh-CN/700.reference/500.sql-reference/100.sql-syntax/300.common-tenant-of-oracle-mode/300.basic-elements-of-oracle-mode/600.annotation-of-oracle-mode/400.hint-of-oracle-mode/150.query-block-name-qb-hint-of-oracle-mode.md)  

OceanBase 数据库的优化器对查询进行分析处理时，会根据查询的结构分解为多个查询块（Query Block），每个块拥有唯一的查询块名（Query Block Name，简称 QB Name）。如果不手动指定，优化器则自动生成 QB Name。

## QB_NAME Hint 的语法与规则

可以使用 QB_NAME Hint 显式为查询块分配 QB Name，语法如下：

```sql
/*+ QB_NAME(qb_name) */

```

下面的例子中，外层查询块被命名为 `qb1`，内联视图（视图 `view_1` 内）为 `qb2`：

```sql
SELECT /*+ QB_NAME(qb1) */ * FROM (SELECT /*+ QB_NAME(qb2) */ * FROM t1) view_1;

```

**使用说明与注意事项：**

- QB Name 不区分大小写。
 - QB Name 不能包含特殊字符。
 - QB Name 限制长度至多 20 个字符。
 - 不能对同一查询块指派多个 QB Name 或不同块使用同一 QB Name。

## 如何使用 Query Block Name

### 定义 Query Block Hint 的作用范围

Query Block Hint 允许在 Hint 内通过指定 Query Block Name 来定义其作用范围。

如下例所示，Hint `index(@qb2 t1 idx)` 虽在查询块 `qb1` 声明，却指定其在查询块 `qb2` 生效：

```sql
SELECT /*+ INDEX(@qb2 t1 idx) QB_NAME(qb1) */ * FROM (SELECT /*+ NO_MERGE QB_NAME(qb2) */ * FROM t1) view_1;

```

### 指定查询中 Hint 作用对象

指定查询中 Hint 作用对象，即对查询中 Hint 的对象进行精确控制。

通过在 Hint 中使用 Query Block Name，可以精确指定作用对象。

如下例所示，使用 `leading` Hint 时，如果未明确指定表的 Query Block Name，则可能导致 Hint 无效：

```sql
SELECT /*+ LEADING(t1@sel$1 t1@sel$2) */ * FROM t1, (SELECT * FROM t1) v WHERE t1.c2 = v.c2;

Query Plan
===========================
|ID|OPERATOR         |NAME|
---------------------------
|0 |HASH JOIN        |    |
|1 |├─TABLE FULL SCAN|t1  |
|2 |└─TABLE FULL SCAN|t1  |
===========================

```

## Query Block Name 自动生成规则

当未指定 QB Name 时，优化器按照以下格式自动生成 Query Block Name：

```sql
query_block_type_str$idx

```

其中 `query_block_type_str$` 为标识 Query Block 类型的字符串，`idx` 为标识该 Query Block 的序号。

下表展示了不同类型的 Query Block 自动生成的名称示例：

| 查询块 | 示例 |
| --- | --- |
| SELECT | SEL$1 |
| UNION ALL/UNION/INTERSECT/MINUS | SET$1 |
| INSERT | INS$1 |
| UPDATE | UPD$1 |
| DELETE | DEL$1 |
| MERGE | MRG$1 |
| REPLACE | REP$1 |
| INSERT ALL | INS_ALL$1 |

如下面的例子所示，`UNION` 会导致优化器为包含这些操作的查询块自动生成 Query Block Name。例如，在使用 `UNION` 的查询中，该查询块自动被命名为 `SET$1`：

```sql
SELECT /*+ USE_HASH_SET(@SET$1) */ c1, c2 FROM t1
UNION
SELECT c1, c2 FROM t2;

```

在这个例子中，Hint `/*+USE_HASH_SET(@SET$1) */` 指示优化器为 `UNION` 操作使用 `HASH DISTINCT SET` 算法。

## 复杂查询中的 Query Block Name

在解析更复杂的查询时，优化器会按照从外到内的顺序为每个查询块分配递增的序号。如果移除手动指定的 QB_NAME Hint，自动生成的 Query Block Names 会如下：

```sql
SELECT /*+ QB_NAME(qb1) */ * FROM (SELECT /*+ QB_NAME(qb2) */ * FROM t1) v;

```

在去掉 QB_NAME Hint 后，外层查询块 `qb1` 的自动生成名字将是 `SEL$1`，而内层块 `qb2` 的名字将是 `SEL$2`。

## 查询改写与 Query Block Name 变化

当查询块触发查询改写时，其 Query Block Name 可以改变。通过使用 `EXPLAIN EXTENDED` 命令，可以在查询计划的 `qb name trace` 中跟踪这些变化。

要确认查询改写之前的自动生成 Query Block Name，可以在查询中包含 `NO_QUERY_TRANSFORMATION` Hint 来禁止所有查询改写，然后使用 `EXPLAIN OUTLINE` 来获取 OUTLINE DATA。通过对 OUTLINE DATA 的 `FULL` 、 `INDEX` 等 Query Block Hint 的分析，可以验证每个 Query Block 的 Name。

例如，在此查询中 `OUTLINE DATA` 的 `FULL(@"SEL$2" "test"."t1"@"SEL$2")` 表明了内联视图 `v` 中的 Query Block Name 为 `SEL$2`：

```sql
SELECT /*+ NO_QUERY_TRANSFORMATION */ COUNT(*)
FROM (SELECT * FROM t1) v GROUP BY c1;

```

 上一篇 下一篇 ![有帮助](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) 咨询热线
