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

Oracle固定执行计划的方法----SQL Profie(三)

原创 数据库路上 2026-10-01
45

Oracle固定执行计划的方法----SQL Profie(三)

继续学习SQL Profile,SQL Profile的基本知识参考文章《Oracle固定执行计划的方法----SQL Profie(一)》、《Oracle固定执行计划的方法----SQL Profie(二)》

一、使用 COE_XFR_SQL_PROFILE 脚本构建SQL Profile——自动化利器

从 MOS(My Oracle Support)可以下载到 SQLT (SQLTXPLAIN) 工具包。其中包含的 coe_xfr_sql_profile.sql 脚本可以自动从 shared pool 或 AWR 中提取指定 SQL ID 的 Outline Data 并生成创建 SQL Profile 的脚本。

主要作用:如果一个SQL语句包含多条执行计划,且经常出现执行速度变化的情况,可以通过该脚本,选择一个预期的执行计划(当前内存中、AWR历史资料库中保存的执行计划),生成SQL Profile,来稳定该语句的执行计划!

备注:类似的脚本还有很多,例如create_sql_profile、create_sql_profile_awr,这里不一一介绍

1、下载与准备

  1. 从 MOS 下载 sqlt.zip 文件(文档 ID: 215187.1)。
  2. 解压后,在 目录中找到 coe_xfr_sql_profile.sql 脚本。

2、执行脚本

首先在 shared pool 中执行目标 SQL:

SELECT /*+ sql_profile_test3 */ t1.*, t2.owner FROM t1, t2 WHERE t1.object_name LIKE '%T1%' AND t1.object_id = t2.object_id; --注意需要查询 plan_hash_value 这一列 set linesize 200 pagesize 999 col sql_text format a40 SELECT sql_text, sql_id, hash_value, child_number,plan_hash_value FROM v$sql WHERE sql_text LIKE '%sql_profile_test3%' AND sql_text NOT LIKE '%v$sql%'; SQL_TEXT SQL_ID HASH_VALUE CHILD_NUMBER PLAN_HASH_VALUE ---------------------------------------- ------------- ---------- ------------ --------------- SELECT /*+ sql_profile_test3 */ t1.*, t2 cdy6d6t5quzfd 1265466829 0 2959412835 .owner FROM t1, t2 WHERE t1.object_name LIKE '%T1%' AND t1.object_id = t2.obje ct_id

执行 coe_xfr_sql_profile.sql 脚本:

@coe_xfr_sql_profile.sql SQL> @coe_xfr_sql_profile.sql Parameter 1: SQL_ID (required) Enter value for 1: cdy6d6t5quzfd ---输入sql_id PLAN_HASH_VALUE AVG_ET_SECS --------------- ----------- 2959412835 .033 Parameter 2: PLAN_HASH_VALUE (required) Enter value for 2: 2959412835 --输入语句想要生成sql profile的plan_hash_value Values passed to coe_xfr_sql_profile: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SQL_ID : "cdy6d6t5quzfd" PLAN_HASH_VALUE: "2959412835" SQL>BEGIN 2 IF :sql_text IS NULL THEN 3 RAISE_APPLICATION_ERROR(-20100, 'SQL_TEXT for SQL_ID &&sql_id. was not found in memory (gv$sqltext_with_newlines) or AWR (dba_hist_sqltext).'); 4 END IF; 5 END; 6 / SQL>SET TERM OFF; SQL>BEGIN 2 IF :other_xml IS NULL THEN 3 RAISE_APPLICATION_ERROR(-20101, 'PLAN for SQL_ID &&sql_id. and PHV &&plan_hash_value. was not found in memory (gv$sql_plan) or AWR (dba_hist_sql_plan).'); 4 END IF; 5 END; 6 / SQL>SET TERM OFF; Execute coe_xfr_sql_profile_cdy6d6t5quzfd_2959412835.sql --生成一个脚本文件,运行该脚本,就可以创建sql profile on TARGET system in order to create a custom SQL Profile with plan 2959412835 linked to adjusted sql_text. COE_XFR_SQL_PROFILE completed.

脚本会生成另一个脚本 coe_xfr_sql_profile_cdy6d6t5quzfd_2959412835.sql。

3、执行生成的脚本

运行生成的脚本即可创建 SQL Profile:

@coe_xfr_sql_profile_cdy6d6t5quzfd_2959412835.sql SQL>@coe_xfr_sql_profile_cdy6d6t5quzfd_2959412835.sql ...... SQL>REM SQL>DECLARE 2 sql_txt CLOB; 3 h SYS.SQLPROF_ATTR; 4 PROCEDURE wa (p_line IN VARCHAR2) IS 5 BEGIN 6 DBMS_LOB.WRITEAPPEND(sql_txt, LENGTH(p_line), p_line); 7 END wa; 8 BEGIN 9 DBMS_LOB.CREATETEMPORARY(sql_txt, TRUE); 10 DBMS_LOB.OPEN(sql_txt, DBMS_LOB.LOB_READWRITE); 11 -- SQL Text pieces below do not have to be of same length. 12 -- So if you edit SQL Text (i.e. removing temporary Hints), 13 -- there is no need to edit or re-align unmodified pieces. 14 wa(q'[SELECT /*+ sql_profile_test3 */ t1.*, t2.owner 15 FROM t1, t2 16 WHERE]'); 17 wa(q'[ t1.object_name LIKE '%T1%' 18 AND t1.object_id = t2.object_id]'); 19 DBMS_LOB.CLOSE(sql_txt); 20 h := SYS.SQLPROF_ATTR( 21 q'[BEGIN_OUTLINE_DATA]', 22 q'[IGNORE_OPTIM_EMBEDDED_HINTS]', 23 q'[OPTIMIZER_FEATURES_ENABLE('11.2.0.4')]', 24 q'[DB_VERSION('11.2.0.4')]', 25 q'[ALL_ROWS]', 26 q'[OUTLINE_LEAF(@"SEL$1")]', 27 q'[FULL(@"SEL$1" "T2"@"SEL$1")]', 28 q'[FULL(@"SEL$1" "T1"@"SEL$1")]', 29 q'[LEADING(@"SEL$1" "T2"@"SEL$1" "T1"@"SEL$1")]', 30 q'[USE_HASH(@"SEL$1" "T1"@"SEL$1")]', 31 q'[END_OUTLINE_DATA]'); 32 :signature := DBMS_SQLTUNE.SQLTEXT_TO_SIGNATURE(sql_txt); 33 :signaturef := DBMS_SQLTUNE.SQLTEXT_TO_SIGNATURE(sql_txt, TRUE); 34 DBMS_SQLTUNE.IMPORT_SQL_PROFILE ( 35 sql_text => sql_txt, 36 profile => h, 37 name => 'coe_cdy6d6t5quzfd_2959412835', 38 description => 'coe cdy6d6t5quzfd 2959412835 '||:signature||' '||:signaturef||'', 39 category => 'DEFAULT', 40 validate => TRUE, 41 replace => TRUE, 42 force_match => FALSE /* TRUE:FORCE (match even when different literals in SQL). FALSE:EXACT (similar to CURSOR_SHARING) */ ); 43 DBMS_LOB.FREETEMPORARY(sql_txt); 44 END; 45 / PL/SQL procedure successfully completed. SQL>WHENEVER SQLERROR CONTINUE SQL>SET ECHO OFF; SIGNATURE --------------------- 10081132228680031145 SIGNATUREF --------------------- 7070267937381023371 ... manual custom SQL Profile has been created COE_XFR_SQL_PROFILE_cdy6d6t5quzfd_2959412835 completed

4、验证 SQL Profile 中的 Hints

SELECT name, category, signature, type, status, force_matching FROM dba_sql_profiles; NAME CATEGORY SIGNATURE TYPE STATUS FOR ------------------------------ -------------- ---------- ------- -------- --- MANUAL_PROFILE_T1_T2 DEFAULT 3.9607E+18 MANUAL ENABLED YES coe_cdy6d6t5quzfd_2959412835 DEFAULT 1.0081E+19 MANUAL ENABLED NO set linesize 200 pagesize 9999 set long 100000 SELECT COMP_DATA FROM dba_sql_profiles a, sys.sqlobj$data b WHERE a.signature = b.signature AND a.name = 'coe_cdy6d6t5quzfd_2959412835'; COMP_DATA -------------------------------------------------------------------------------- <outline_data><hint><![CDATA[BEGIN_OUTLINE_DATA]]></hint><hint><![CDATA[IGNORE_O PTIM_EMBEDDED_HINTS]]></hint><hint><![CDATA[OPTIMIZER_FEATURES_ENABLE('11.2.0.4' )]]></hint><hint><![CDATA[DB_VERSION('11.2.0.4')]]></hint><hint><![CDATA[ALL_ROW S]]></hint><hint><![CDATA[OUTLINE_LEAF(@"SEL$1")]]></hint><hint><![CDATA[FULL(@" SEL$1" "T2"@"SEL$1")]]></hint><hint><![CDATA[FULL(@"SEL$1" "T1"@"SEL$1")]]></hin t><hint><![CDATA[LEADING(@"SEL$1" "T2"@"SEL$1" "T1"@"SEL$1")]]></hint><hint><![C DATA[USE_HASH(@"SEL$1" "T1"@"SEL$1")]]></hint><hint><![CDATA[END_OUTLINE_DATA]]> </hint></outline_data>

5、脚本的注意事项

  • 脚本会从 shared pool 和 AWR 中获取 SQL 执行的各个执行计划的统计信息。
  • 需要输入你认为正确的、需要稳定的执行计划的 hash value。
  • 生成的 SQL Profile 名称格式为:coe + sql_id + plan_hash_value。
  • force_match 默认为 FALSE,可以手工修改生成的脚本将其改为 TRUE。
  • 也可以按需要修改生成脚本的其他内容。

二、高级技巧:在不修改 SQL 的情况下改变执行计划

在实际生产环境中,常常遇到这样的情况:SQL 语句的执行计划有问题,或者 SQL 使用了错误的 Hints(例如 /*+ RULE */),但应用代码不能修改或短期内无法修改。

有三种解决办法:

  1. 调整统计信息——不推荐,因为复杂、不稳定(统计信息可能被重新收集),且影响面广。
  2. 使用 Outline——方法复杂。
  3. 使用 SQL Profile——推荐方案。

1、解决思路:“乾坤大挪移”

使用 SQL Profile 改变 SQL 执行计划的核心思路是:

  1. 取得原始 SQL 的文本(如有可能还包括 SQL_ID)
  2. 通过 COE_XFR_SQL_PROFILE脚本生成构建sql profile的脚本。
  3. 构造一个与原始 SQL 在逻辑上、结构上完全相同的 SQL。
  4. 执行构造的 SQL,通过 COE_XFR_SQL_PROFILE脚本生成新的构建sql profile的脚本。
  5. 修改第二步生成的COE脚本内容修改(修改OUTLINE部分),使用第四步的COE脚本内容中的(OUTLINE DATA)。

2、案例演示

第一步:原始 SQL(待调整的执行计划)

SELECT /*+ old_sql full(t1) full(t2) use_hash(t1 t2) */ t1.*, t2.owner FROM t1, t2 WHERE t1.object_name LIKE '%T1%' AND t1.object_id = t2.object_id; set linesize 200 pagesize 999 col sql_text format a40 SELECT sql_text, sql_id, hash_value, child_number,plan_hash_value FROM v$sql WHERE sql_text LIKE '%old_sql%' AND sql_text NOT LIKE '%v$sql%'; SQL_TEXT SQL_ID HASH_VALUE CHILD_NUMBER PLAN_HASH_VALUE ---------------------------------------- ------------- ---------- ------------ --------------- SELECT /*+ old_sql full(t1) full(t2) use g7ndz4jp2j3uh 1781043024 0 2959412835 _hash(t1 t2) */ t1.*, t2.owner FROM t1, t2 WHERE t1.object_name LIKE '%T1%' AN D t1.object_id = t2.object_id

执行计划:

select * from table(dbms_xplan.display_cursor('g7ndz4jp2j3uh','',''));

Plan hash value: 2959412835
-----------------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |       |       |       |  5854 (100)|          |
|*  1 |  HASH JOIN         |      |  2500K|    97M|  1968K|  5854   (7)| 00:01:11 |
|   2 |   TABLE ACCESS FULL| T2   | 87356 |   938K|       |   344   (1)| 00:00:05 |
|*  3 |   TABLE ACCESS FULL| T1   |  2500K|    71M|       |   437  (84)| 00:00:06 |
-----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
   3 - filter(("T1"."OBJECT_NAME" LIKE '%T1%' AND "T1"."OBJECT_NAME" IS NOT NULL))   

原始 SQL 中使用了 FULL(t1)、FULL(t2) 和 USE_HASH(t1 t2) 这些 Hints,强制使用全表扫描 + 哈希连接。执行后 SQL_ID 为 g7ndz4jp2j3uh。

第二步:通过 COE_XFR_SQL_PROFILE脚本生成构建sql profile的脚本

SQL>@coe_xfr_sql_profile.sql
Parameter 1:
SQL_ID (required)
Enter value for 1: g7ndz4jp2j3uh

PLAN_HASH_VALUE AVG_ET_SECS
--------------- -----------
     2959412835        .057

Parameter 2:
PLAN_HASH_VALUE (required)

Enter value for 2: 2959412835

Values passed to coe_xfr_sql_profile:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SQL_ID         : "g7ndz4jp2j3uh"
PLAN_HASH_VALUE: "2959412835"

......

Execute coe_xfr_sql_profile_g7ndz4jp2j3uh_2959412835.sql
on TARGET system in order to create a custom SQL Profile
with plan 2959412835 linked to adjusted sql_text.
COE_XFR_SQL_PROFILE completed.

第三步:构造目标 SQL(我们希望的执行计划)

构造一条在逻辑上和结构上与原始 SQL 完全相同的 SQL,但使用我们希望的执行计划:

SELECT /*+ new_sql index(t2) use_nl(t1 t2) */ t1.*, t2.owner FROM t1, t2 WHERE t1.object_name LIKE '%T1%' AND t1.object_id = t2.object_id; set linesize 200 pagesize 999 col sql_text format a40 SELECT sql_text, sql_id, hash_value, child_number,plan_hash_value FROM v$sql WHERE sql_text LIKE '%new_sql%' AND sql_text NOT LIKE '%v$sql%'; SQL_TEXT SQL_ID HASH_VALUE CHILD_NUMBER PLAN_HASH_VALUE ---------------------------------------- ------------- ---------- ------------ --------------- SELECT /*+ new_sql index(t2) use_nl(t1 t 0sz1znbny6v0m 3923995667 0 1386590592 2) */ t1.*, t2.owner FROM t1, t2 WHERE t 1.object_name LIKE '%T1%' AND t1.objec t_id = t2.object_id

执行计划:

select * from table(dbms_xplan.display_cursor('0sz1znbny6v0m','',''));
Plan hash value: 1386590592
---------------------------------------------------------------------------------------
| Id  | Operation                    | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |        |       |       |  5001K(100)|          |
|   1 |  NESTED LOOPS                |        |  2500K|    97M|  5001K  (1)| 16:40:18 |
|   2 |   NESTED LOOPS               |        |  2500K|    97M|  5001K  (1)| 16:40:18 |
|*  3 |    TABLE ACCESS FULL         | T1     |  2500K|    71M|   437  (84)| 00:00:06 |
|*  4 |    INDEX RANGE SCAN          | IND_T2 |     1 |       |     1   (0)| 00:00:01 |
|   5 |   TABLE ACCESS BY INDEX ROWID| T2     |     1 |    11 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter(("T1"."OBJECT_NAME" LIKE '%T1%' AND "T1"."OBJECT_NAME" IS NOT NULL))
   4 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")

第四步:通过 COE_XFR_SQL_PROFILE脚本,提取构造 SQL 的SQL Profile

使用 coe_xfr_sql_profile.sql 脚本提取构造 SQL 的 Outline Data:

@coe_xfr_sql_profile.sql -- 输入构造 SQL 的 SQL_ID(0sz1znbny6v0m)和 PLAN_HASH_VALUE(1386590592) -- /*+ new_sql index(t2) use_nl(t1 t2) */SQL 的 Outline Data SQL>@coe_xfr_sql_profile.sql Parameter 1: SQL_ID (required) Enter value for 1: 0sz1znbny6v0m PLAN_HASH_VALUE AVG_ET_SECS --------------- ----------- 1386590592 .033 Parameter 2: PLAN_HASH_VALUE (required) Enter value for 2: 1386590592 Values passed to coe_xfr_sql_profile: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SQL_ID : "0sz1znbny6v0m" PLAN_HASH_VALUE: "1386590592" ...... SQL>SET TERM OFF; Execute coe_xfr_sql_profile_0sz1znbny6v0m_1386590592.sql on TARGET system in order to create a custom SQL Profile with plan 1386590592 linked to adjusted sql_text. COE_XFR_SQL_PROFILE completed.

生成的脚本 coe_xfr_sql_profile_0sz1znbny6v0m_1386590592.sql 中包含 Outline Data:

h := SYS.SQLPROF_ATTR( q'[BEGIN_OUTLINE_DATA]', q'[IGNORE_OPTIM_EMBEDDED_HINTS]', q'[OPTIMIZER_FEATURES_ENABLE('11.2.0.4')]', q'[DB_VERSION('11.2.0.4')]', q'[ALL_ROWS]', q'[OUTLINE_LEAF(@"SEL$1")]', q'[FULL(@"SEL$1" "T1"@"SEL$1")]', q'[INDEX(@"SEL$1" "T2"@"SEL$1" ("T2"."OBJECT_ID"))]', q'[LEADING(@"SEL$1" "T1"@"SEL$1" "T2"@"SEL$1")]', q'[USE_NL(@"SEL$1" "T2"@"SEL$1")]', q'[NLJ_BATCHING(@"SEL$1" "T2"@"SEL$1")]', q'[END_OUTLINE_DATA]');

第五步:修改第二步的脚本内容

针对原始 SQL(SQL_ID = g7ndz4jp2j3uh,PLAN_HASH_VALUE = 2959412835)使用 coe_xfr_sql_profile.sql 生成脚本。

然后手工修改生成的脚本 coe_xfr_sql_profile_g7ndz4jp2j3uh_2959412835.sql:

  1. 将 h := SYS.SQLPROF_ATTR(...) 那段替换成第四步得到的 Outline Data。

    q'[BEGIN_OUTLINE_DATA]',
    q'[IGNORE_OPTIM_EMBEDDED_HINTS]',
    q'[OPTIMIZER_FEATURES_ENABLE('11.2.0.4')]',
    q'[DB_VERSION('11.2.0.4')]',
    q'[ALL_ROWS]',
    q'[OUTLINE_LEAF(@"SEL$1")]',
    q'[FULL(@"SEL$1" "T2"@"SEL$1")]',
    q'[FULL(@"SEL$1" "T1"@"SEL$1")]',
    q'[LEADING(@"SEL$1" "T2"@"SEL$1" "T1"@"SEL$1")]',
    q'[USE_HASH(@"SEL$1" "T1"@"SEL$1")]',
    q'[END_OUTLINE_DATA]');
    改为
    q'[BEGIN_OUTLINE_DATA]',
    q'[IGNORE_OPTIM_EMBEDDED_HINTS]',
    q'[OPTIMIZER_FEATURES_ENABLE('11.2.0.4')]',
    q'[DB_VERSION('11.2.0.4')]',
    q'[ALL_ROWS]',
    q'[OUTLINE_LEAF(@"SEL$1")]',
    q'[FULL(@"SEL$1" "T1"@"SEL$1")]',
    q'[INDEX(@"SEL$1" "T2"@"SEL$1" ("T2"."OBJECT_ID"))]',
    q'[LEADING(@"SEL$1" "T1"@"SEL$1" "T2"@"SEL$1")]',
    q'[USE_NL(@"SEL$1" "T2"@"SEL$1")]',
    q'[NLJ_BATCHING(@"SEL$1" "T2"@"SEL$1")]',
    q'[END_OUTLINE_DATA]');
    
  2. 将 force_match 从 FALSE 改为 TRUE。

第六步:执行修改后的脚本

@@coe_xfr_sql_profile_g7ndz4jp2j3uh_2959412835.sql PL/SQL 过程已成功完成。 SIGNATURE --------------------- 15211772502623681692 SIGNATUREF --------------------- 1099879712749910124 ... manual custom SQL Profile has been created COE_XFR_SQL_PROFILE_g7ndz4jp2j3uh_2959412835 completed

第七步:验证效果

执行原始 SQL:

SELECT /*+ old_sql full(t1) full(t2) use_hash(t1 t2) */ t1.*, t2.owner FROM t1, t2 WHERE t1.object_name LIKE '%T1%' AND t1.object_id = t2.object_id; set linesize 200 pagesize 999 col sql_text format a40 SELECT sql_text, sql_id, hash_value, child_number,plan_hash_value 2 FROM v$sql 3 WHERE sql_text LIKE '%old_sql%' 4 AND sql_text NOT LIKE '%v$sql%'; SQL_TEXT SQL_ID HASH_VALUE CHILD_NUMBER PLAN_HASH_VALUE ---------------------------------------- ------------- ---------- ------------ --------------- SELECT /*+ old_sql full(t1) full(t2) use g7ndz4jp2j3uh 1781043024 0 1386590592 _hash(t1 t2) */ t1.*, t2.owner FROM t1, t2 WHERE t1.object_name LIKE '%T1%' AN D t1.object_id = t2.object_id

执行计划:

SQL>select * from table(dbms_xplan.display_cursor('g7ndz4jp2j3uh','',''));
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------
SQL_ID  g7ndz4jp2j3uh, child number 0
-------------------------------------
SELECT /*+ old_sql full(t1) full(t2) use_hash(t1 t2) */ t1.*, t2.owner
FROM t1, t2 WHERE t1.object_name LIKE '%T1%'   AND t1.object_id =
t2.object_id
Plan hash value: 1386590592
---------------------------------------------------------------------------------------
| Id  | Operation                    | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |        |       |       |  5001K(100)|          |
|   1 |  NESTED LOOPS                |        |  2500K|    97M|  5001K  (1)| 16:40:18 |
|   2 |   NESTED LOOPS               |        |  2500K|    97M|  5001K  (1)| 16:40:18 |
|*  3 |    TABLE ACCESS FULL         | T1     |  2500K|    71M|   437  (84)| 00:00:06 |
|*  4 |    INDEX RANGE SCAN          | IND_T2 |     1 |       |     1   (0)| 00:00:01 |
|   5 |   TABLE ACCESS BY INDEX ROWID| T2     |     1 |    11 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - filter(("T1"."OBJECT_NAME" LIKE '%T1%' AND "T1"."OBJECT_NAME" IS NOT   NULL))
   4 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
Note
-----
   - SQL profile coe_g7ndz4jp2j3uh_2959412835 used for this statement

成功! SQL Profile 起作用了,执行计划从全表扫描 + 哈希连接变成了嵌套循环连接 + 索引范围扫描。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论