---
title: 如何使用 outline 绑定执行计划 -OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于 如何使用 outline 绑定执行计划 相关的常见问题和使用技巧，帮助您快速解决 如何使用 outline 绑定执行计划 的难题。
---
切换语言

- 简体中文
- English

划线反馈

# 如何使用 outline 绑定执行计划

更新时间：2024-01-22 01:56

适用版本： V2.1.x、V2.2.x、V3.1.x、V3.2.x 内容类型：How-to  

通过在 SQL 中添加 HINT 可以控制优化器按 HINT 指定的行为进行计划生成，直接在 SQL 语句中添加 HINT 的方法适用于在系统上线前，对于已上线的业务，如果出现优化器选择的计划不够优时，则需要在线进行计划绑定，通过对某条 SQL 创建 OUTLINE 可达到计划绑定的目的。

## 创建 OUTLINE

OceanBase 数据库支持通过两种方式创建 OUTLINE，一种是通过 SQL_TEXT (用户执行的带参数的原始语句)，另一种是通过 SQL_ID 创建。

#### 注意

建 OUTLINE 前需要先进入对应的数据库。

### 使用 SQL_TEXT 创建

使用 SQL_TEXT 创建 OUTLINE 后，会生成一个 key-value 对存储在 map 中，其中 key 为绑定的 SQL参数化后的值，value 为绑定的 HINT。

```unknow
CREATE [OR REPLACE] OUTLINE outline_name ON stmt [ TO target_stmt ];

```

其中：

- 指定 `OR REPLACE` 后，可以对已经存在的 OUTLINE 进行替换。
 - `stmt` 一般为一个带有 HINT 和原始参数的 DML 语句。
 - 如果不指定 `TO target_stmt`， 则表示如果数据库接受的 SQL 参数化后与 stmt 去掉 HINT 参数化文本相同，则将该 SQL 绑定 stmt 中 HINT 生成执行计划。
 - 如果期望对含有 HINT 的语句进行固定计划，则需要 `TO target_stmt` 来指明原始的 SQL。

  #### 注意

  在使用 `TO target_stmt` 子句时，要求原始 SQL `stmt` 与 `target_stmt` 在去掉 HINT 后完全匹配

### 使用 SQL_ID 创建

使用 SQL_ID 创建的语法如下所示。

```unknow
CREATE OUTLINE outline_name ON sql_id USING HINT hint;

```

sql_id 为需要绑定的 SQL 对应的 SQL_ID。SQL_ID 可通过以下几种方式获取。

- 查询 `gv$plan_cache_plan_stat` 表获取。
 - 查询 `gv$sql_audit` 表获取。
 - 通过参数化的原始 SQL，使用 MD5 生成。

  具体可使用下面这个脚本生成对应 SQL 的 SQL_ID。

  ```python
  >>> import hashlib
  >>> sql_text='SELECT * FROM t1 WHERE c2 = ?'
  >>> sql_id=hashlib.md5(sql_text.encode('utf-8')).hexdigest().upper()
  >>> print(sql_id)

  ```

## 删除 OUTLINE

删除 OUTLINE 后，对应 SQL 重新生成计划时将不再依据绑定的 OUTLINE 生成。

删除 OUTLINE 的语法如下。

```unknow
 obclient> DROP OUTLINE outline_name;

```

#### 注意

删除 OUTLINE 需要在 `outline_name` 中指定数据库名称，或者在执行 `USE database` 后再删除

## 确认 OUTLINE 生效

通过以下步骤确认创建的 OUTLINE 是否生效。

1. 确定创建 OUTLINE 是否成功。

   通过查看 `gv$outline` 表，确认是否成功创建对应的名称的 OUTLINE。

   如果结果不为空，则表示 OUTLINE 创建成功。

   ```unknow
   obclient> SELECT * FROM oceanbase.gv$outline WHERE outline_name = 'otl_idx_c2'\G;
   *************************** 1. row ***************************
           tenant_id: 1001
         database_id: 1100611139404776
          outline_id: 1100611139404777
       database_name: test
        outline_name: otl_idx_c2
   visible_signature: SELECT * FROM t1 WHERE c2 = ?
            sql_text: SELECT/*+ index(t1 idx_c2)*/ * FROM t1 WHERE c2 = 1
      outline_target:
         outline_sql: SELECT /*+ BEGIN_OUTLINE_DATA INDEX(@"SEL$1" "test.t1"@"SEL$1" "idx_c2") END_OUTLINE_DATA*/* FROM t1 WHERE c2 = 1

   ```
 2. 确定新的 SQL 执行是否通过绑定的OUTLINE生成了新计划。

   当绑定 OUTLINE 的 SQL 有新的流量查询后，查询 `(g)v$plan_cache_plan_stat` 表中该 SQL 对应的计划信息中 `outline_id`。

   如果 outline_id 是在 `gv$outline` 中查到的 `outline_id`，则表示该计划是绑定的 outline 生成的执行计划。

   ```unknow
   obclient> SELECT sql_id, plan_id, statement, outline_id, outline_data
           FROM oceanbase.gv$plan_cache_plan_stat
               WHERE statement LIKE '%SELECT * FROM t1 WHERE c2 =%'\G
   *************************** 1. row ***************************
         sql_id: ED570339F2C856BA96008A29EDF04C74
        plan_id: 17225
      statement: SELECT * FROM t1 WHERE c2 = ?
     outline_id: 1100611139404777
   outline_data: /*+ BEGIN_OUTLINE_DATA INDEX(@"SEL$1" "test.t1"@"SEL$1" "idx_c2") END_OUTLINE_DATA*/

   ```
 3. 确定生成的执行计划是否符合预期。

   通过查询 `gv$plan_cache_plan_explain` 表查看 `plan_cache` 中缓存的执行计划，查看执行计划是否符合预期。

   ```unknow
   SELECT OPERATOR, NAME
    FROM oceanbase.gv$plan_cache_plan_explain
    WHERE tenant_id = 1001 AND ip = 'xxx.xxx.xxx.xxx'
          AND port = 30474 AND plan_id = 17225;

   +--------------------+------------+
   | OPERATOR           | NAME       |
   +--------------------+------------+
   |  PHY_ROOT_TRANSMIT | NULL       |
   |   PHY_TABLE_SCAN   | t1(idx_c2) |
   +--------------------+------------+

   ```

Previous

[如何查看 SQL 执行的物理执行计划](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000217862)

Next

[Oracle 租户下包含 rownum 时查看执行计划中相关的信息](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000217880) ![有帮助](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) 咨询热线
