亳州市网站建设_网站建设公司_建站流程_seo优化
2025/12/26 23:21:00 网站建设 项目流程

一、 区别

1、 hint注入

Hint注入是通过系统函数为SQL语句动态添加优化器指令的技术。通过SQL注释语法(/+ ... /)向优化器传递指令,干预其生成执行计划的决策过程(如强制索引、连接顺序)。通过系统函数 sf_inject_hint 创建全局规则,将HINT指令与特定SQL绑定,无需修改原SQL文本即可干预优化器行为。规则存储在系统视图 SYSINJECTHINT 中,由数据库自动匹配应用。通过参数ENABLE_INJECT_HINT=1全局开启Hint注入。 核心特点:

  1. )无需修改SQL文本。
  2. )DDL变更导致失效,表结构变更(如删除索引)后,强制索引的HINT会报错。
  3. )修改规则后,SQL仍使用旧执行计划,需手动清理计划缓存。
  4. )支持按SQL文本绑定和按HASH_VALUE绑定。

2、持久化绑定计划

持久化绑定计划指将已生成的执行计划持久化存储至系统表(SYSPLNINFO)中,确保数据库重启后仍可加载使用,从而避免执行计划因环境变化(如迁移、升级)而失效,保障性能稳定性。数据库重启后通过参数LOAD_BINDED_PLN=1自动加载,确保计划跨会话、跨重启的稳定性。 核心特点:

  1. )固化现有计划:跳过优化器阶段:直接复用存储的计划,避免因统计信息更新、索引变更等导致执行计划变动。
  2. )持久化存储:计划存入系统表,不受重启影响。
  3. )表结构变更(如删列、改类型)会导致绑定计划自动失效。
  4. )支持按SQL文本绑定和按HASH_VALUE绑定。
  5. )分为内存绑定与持久化绑定

绑定状态标识:在动态视图 V$CACHEPLN 中通过 BINDED 字段区分绑定类型:

'N':未绑定 'M':内存绑定(重启失效) 'P':持久化绑定 'B':内存绑定与持久化绑定同时生效。

二、适用场景

1、hint注入

  1. )紧急性能问题修复:当关键SQL因优化器缺陷(如错误选择索引或连接方式)导致性能骤降时,通过Hint注入强制指定执行路径。无需重启应用或修改SQL文本,实时生效。
  2. )规避全局参数风险:需调整优化器参数(如OPTIMIZER_OR_NBEXP),但全局修改会影响其他业务SQL。会话级或SQL级精准控制,避免全局参数副作用。
  3. )解决统计信息失真问题:统计信息未及时更新或采样率不足导致计划劣化(如全表扫描替代索引扫描)。

2、持久化绑定计划

  1. )核心交易系统性能保障:高频交易类SQL(如支付、清算)需绝对稳定的执行计划,避免因统计信息更新、索引变更等导致计划突变引发性能抖动。计划存入系统表 SYSPLNINFO,重启后通过 LOAD_BINDED_PLN=1 自动加载,彻底规避计划漂移风险。
  2. )统计信息采集不及时或采样率不足时,优化器可能生成劣质计划(如全表扫描替代索引扫描)。在统计信息准确时绑定最优计划,后续统计信息更新不会触发计划重生成。
  3. )数据库迁移/升级场景:跨版本升级或异构迁移(如Oracle→达梦)时,需保持原执行计划一致性,避免因优化器差异导致性能回退。

三、操作步骤

准备测试环境

创建测试表

create table DMHR.TAB01 ( ID INT not null , NAME VARCHAR2(10), ADDRESS VARCHAR2(10), primary key("ID") );

创建测试数据

insert into DMHR.TAB01 values(1,'Tony','Beijing'); insert into DMHR.TAB01 values(2,'Jason','USA'); insert into DMHR.TAB01 values(3,'Tracy','JP'); commit;

检查默认的执行计划

select * from DMHR.TAB01 t where t.ID=1; 1 #NSET2: [1, 1, 112] 2 #PRJT2: [1, 1, 112]; exp_num(4), is_atom(FALSE) 3 #BLKUP2: [1, 1, 112]; INDEX33555511(T) 4 #SSEK2: [1, 1, 112]; scan_type(ASC), INDEX33555511(TAB01 as T), scan_range[1,1], is_global(0)

强制不走索引

select /*+ NO_INDEX(t INDEX33555511) */ * from DMHR.TAB01 t where t.ID=1; 1 #NSET2: [1, 1, 112] 2 #PRJT2: [1, 1, 112]; exp_num(4), is_atom(FALSE) 3 #SLCT2: [1, 1, 112]; T.ID = 1 SLCT_PUSHDOWN(TRUE) 4 #CSCN2: [1, 3, 112]; INDEX33555510(TAB01 as T) NEED_SLCT(TRUE); btr_scan(1)

1、hint注入

1)根据sql模糊匹配

可通过SYSINJECTHINT 视图查看已指定的SQL 语句和对应的HINT。 select * from SYSINJECTHINT ; 如需修改注入的sql信息,可先删除INJECT,再重新创建,例: SF_DEINJECT_HINT 函数可以将设置INJECT hint删除。 sf_deinject_hint('TESTJOIN',false); 添加INJECT语法: sf_inject_hint( sql_text => ' select * from v$sessions a ,v$session_stat b where a.sess_id=b.sessid;', hint_text =>'use_nl(a,b)', name =>'TESTJOIN', description => 'this is a test join hint.', validate => true, fuzzy => true, --模糊匹配 need_clear=>false --不清空全库执行计划 ); 0 测试案例: 通过参数ENABLE_INJECT_HINT=1全局开启Hint注入 sp_set_para_value(1,'ENABLE_INJECT_HINT',1) sf_inject_hint( sql_text => 'select * from DMHR.TAB01 t where t.ID=1;', hint_text =>'NO_INDEX(t INDEX33555511) ', name =>'TESTJOIN', description => 'this is a test join hint.', validate => true, fuzzy => true, --模糊匹配 need_clear=>false --不清空全库执行计划 ); 检查新产生的注入: select * from SYSINJECTHINT; TESTJOIN this is a test join hint. TRUE <长文本> <长文本> SYSDBA 2025-12-26 12:45:38.373365 1 NULL NULL 检查SQL 产生的执行计划: select * from DMHR.TAB01 t where t.ID=1; <===一定要完全和绑定是的SQL。 1 #NSET2: [1, 1, 112] 2 #PRJT2: [1, 1, 112]; exp_num(4), is_atom(FALSE) 3 #SLCT2: [1, 1, 112]; T.ID = 1 SLCT_PUSHDOWN(TRUE) 4 #CSCN2: [1, 3, 112]; INDEX33555510(TAB01 as T) NEED_SLCT(TRUE); btr_scan(1) 检查是否命中了hint select * from V$INJECT_HINT_INFO; 1836374296 select * from DMHR.TAB01 t where t.ID=1; TESTJOIN NO_INDEX(t INDEX33555511) 2025-12-26 12:47:56 2025-12-26 12:47:56 1 Y TRUE

2)根据sql_text_id 绑定

--查询sql_text_id SELECT SQL_TEXT_ID,SQL_TEXT FROM SYS.V$SQLTEXT WHERE SQL_TEXT LIKE 'select * from DMHR.TAB01 t where t.ID=1;'; sn5u4cg7brg5h select * from DMHR.TAB01 t where t.ID=1; --清除之前的HINT 注入 SF_DEINJECT_HINT('TESTJOIN'); --确认之前的HINT 被清除 select * from SYSINJECTHINT; --使用sql_text_id进行hint注入 SF_INJECT_HINT('sn5u4cg7brg5h','NO_INDEX(t INDEX33555511)','TESTJOIN01','',TRUE,2); --sql_text:待注入 HINT 规则的 SQL 语句。fuzzy 参数类型为 INT 时,值为 2 表示支持通过 sql_text_id 指定待注入的 SQL 语句,sql_text_id 字段可通过 V$SQLTEXT 视图进行查询 --validate:HINT 规则是否生效。TRUE 是;FALSE 否 确认新HINT 的注入 select * from SYSINJECTHINT; 检查SQL 的执行计划 select * from DMHR.TAB01 t where t.ID=1; 1 #NSET2: [1, 1, 112] 2 #PRJT2: [1, 1, 112]; exp_num(4), is_atom(FALSE) 3 #SLCT2: [1, 1, 112]; T.ID = 1 SLCT_PUSHDOWN(TRUE) 4 #CSCN2: [1, 3, 112]; INDEX33555510(TAB01 as T) NEED_SLCT(TRUE); btr_scan(1) 检查HINT 的命中情况 select * from V$INJECT_HINT_INFO;

2、持久化绑定计划

1)清空执行计划缓存

sp_clear_plan_cache(); 删除上面的HINT 注入 SF_DEINJECT_HINT('TESTJOIN01');

2)执行SQL 生成新的待绑定的执行计划

注意:需要实际执行

select /*+ NO_INDEX(t INDEX33555511) */ * from DMHR.TAB01 t where t.ID=1; 1 #NSET2: [1, 1, 112] 2 #PRJT2: [1, 1, 112]; exp_num(4), is_atom(FALSE) 3 #SLCT2: [1, 1, 112]; T.ID = 1 SLCT_PUSHDOWN(TRUE) 4 #CSCN2: [1, 3, 112]; INDEX33555510(TAB01 as T) NEED_SLCT(TRUE); btr_scan(1)

3)持久化绑定

获取模式的 ID SELECT SCHID FROM SYSOBJECTS WHERE NAME='SYSDBA' AND TYPE$='SCH' 0 获取SQL 的HASH_VALUE SELECT HASH_VALUE FROM V$CACHEPLN WHERE SQLSTR LIKE 'select /*+ NO_INDEX(t INDEX33555511) */ * from DMHR.TAB01 t where t.ID=1;'; SELECT HASH_VALUE FROM SYS.V$SQLTEXT WHERE SQL_TEXT LIKE 'select /*+ NO_INDEX(t INDEX33555511) */ * from DMHR.TAB01 t where t.ID=1;'; -1226422453 SP_SET_PLN_BINDED(-1226422453,'SYSDBA', 'SQL', 2); 说明: SP_SET_PLN_BINDED( sql_text VARCHAR(32767), -- SQL语句文本(需完整匹配)或 SQL哈希值(从 `V$CACHEPLN.HASH_VALUE`或`V$SQLTEXT.HASH_VALUE` 获取) schid INTEGER, -- 模式ID(可通过 `SELECT SCHID FROM SYSOBJECTS WHERE NAME='模式名' AND TYPE$='SCH'` 获取) type VARCHAR(12), -- 语句类型:'SQL'(查询语句)或 'PL/OBJ'(存储过程/触发器) binded INTEGER -- 绑定类型:0(解绑)、1(内存绑定)、2(持久化绑定) );

4)查询系统中绑定执行计划持久化的信息。

select * from SYSPLNINFO; 1 -1226422453 150994945 7 select /*+ NO_INDEX(t INDEX33555511) */ * from DMHR.TAB01 t where t.ID=1; <二进制> 11 1 N --查询系统中绑定执行计划对应字典对象的信息。 select * from SYSPLNOBJID; 1 150995946 1 1036 1 33555510 --针对sql查询是否已添加持久化绑定 select * from v$cachepln where HASH_VALUE='-1226422453';

5)移除和禁用

移除系统表 SYSPLNINFO 中 PLN_ID 为 1 的执行计划

SP_REMOVE_STORE_PLN(1);

–禁用系统表 SYSPLNINFO 中 PLN_ID 为 1 的执行计划

SP_SET_PLN_DISABLED(1,1);--解开禁用是0

6)确认持久化计划是否生效

可以通过dmp 直接计划方式导出新的执行计划

–先确认SQL 对应的执行计划缓存号cache_item

select cache_item,sqlstr,* from v$cachepln where sqlstr like '%select /*+ NO_INDEX(t INDEX33555511) */ * from DMHR.TAB01 t where t.ID=1;%' ; 139649798914888 select /*+ NO_INDEX(t INDEX33555511) */ * from DMHR.TAB01 t where t.ID=1; 139649798914888 SQL -1226422453 150994945 50331649 0 N 0 1 1036 select /*+ NO_INDEX(t INDEX33555511) */ * from DMHR.TAB01 t where t.ID=1; 139649808224424 NULL 160 7 0 0 3 Y 56444 Y P Y N

–打印内存中的缓存计划执行以下命令,打印出缓存计划到默认路径,默认路径在数据库实例目录的trace文件夹中 –假定cache_item=139649798914888

alter session set events 'immediate trace name plndump,level 139649798914888';

欢迎访问达梦技术分享社区 ECO

https://eco.dameng.com

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询