达梦数据库如何实现不更改SQL而改变其执行计划

SQL优化中,有时数据库选择的执行计划并不是最优的,这时会考虑使用HINT提示来改变SQL的执行计划(比如索引扫描修改为全表扫描、嵌套循环连接修改为哈希连接)。但使用HINT提示需要修改对应的SQL语句,增加HINT子句,在应用中不是很方便,此时可以使用SF_INJECT_HINT函数来绑定SQL语句使其使用对应的HINT。

本章内容已在如下环境中测试:

操作系统:银河麒麟V10

数据库:DM8

相关关键字:DM数据库、INJECT HINT、HINT提示

一、HINT提示

如下SQL,默认两表关联使用的是哈希连接HASH JOIN:

explain select a.department_id, a.employee_name, b.department_name
from dmhr.employee a, dmhr.department b
where a.department_id = b.department_id;

使用hint改变其执行计划,修改SQL增加HINT提示 /*+use_nl(a,b) */使其使用内嵌套循环连接:

explain select /*+use_nl(a,b) */ a.department_id, a.employee_name, b.department_name
from dmhr.employee a, dmhr.department b
where a.department_id = b.department_id;

二、INJECT HINT函数

HINT提示需要修改SQL语句, SF_INJECT_HINT函数提供无需修改 SQL 语句依然能按照指定的 HINT 运行语句的相关功能。支持SQL精确匹配和模糊匹配。

使用时的限制条件如下:

(1)INI参数ENABLE_INJECT_HINT需设置为1;

(2)SQL只能是语法正确的增删改查语句;

(3)SQL会经过系统格式化,格式化之后的SQL和指定的规则名称必须全局唯一;

(4)HINT一指定,则全局生效;

(5)系统检查SQL匹配时,必须是整条语句完全匹配,不能是语句中子查询匹配;

(6)可通过 SYSINJECTHINT 视图查看已指定的 SQL 语句和对应的 HINT。

2.1 使用前提

使用SF_INJECT_HINT函数需设置INI 参数 ENABLE_INJECT_HINT为1;

select * from v$dm_ini t where para_name = 'ENABLE_INJECT_HINT';
alter system set 'ENABLE_INJECT_HINT'=1 both;

2.2 INJECT HINT函数使用示例(精确匹配)

使用SF_INJECT_HINT函数指定SQL HINT,默认是精确匹配SQL:

sf_inject_hint(
sql_text => 'select a.department_id, a.employee_name, b.department_name from dmhr.employee a, dmhr.department b where a.department_id = b.department_id;',
hint_text =>'use_nl(a,b)',
name =>'TESTSQL',
description => 'this is a test hint',
validate => true);

这里指定SQL语句的两表关联使用nest loop join,指定后查看该sql的执行计划,可以看到执行计划显示nest loop join。

explain select a.department_id, a.employee_name, b.department_name from dmhr.employee a, dmhr.department b where a.department_id = b.department_id;

2.3 INJECT HINT函数使用示例(模糊匹配)

SF_INJECT_HINT函数精确匹配要求SQL必须严格一致。有的业务SQL较长,查询字段不同、语句中间有空格等,这时精确匹配的规则会使指定HINT无法生效。此时可以使用SF_INJECT_HINT函数的fuzzy 参数使其支持SQL模糊匹配。

例如,指定如下SQL的模糊匹配:

sf_inject_hint(
sql_text => 'from dmhr.employee a, dmhr.department b where a.department_id=b.department_id',
hint_text =>'use_nl(a,b)',
name =>'TESTJOIN',
description => 'this is a test join hint.',
validate => true,
fuzzy = true
);

查看SQL执行计划,比如查询两张表所有列信息,可以看到两表使用nest loop join。

explain select a.*, b.* from dmhr.employee a, dmhr.department b where a.department_id=b.department_id;

HINT提示支持设置INI参数,比如设置ENABLE_HASH_JOIN参数为0,也可以实现相同的功能:

sf_inject_hint(
sql_text => 'from dmhr.employee a, dmhr.department b where a.department_id=b.department_id',
hint_text =>'ENABLE_HASH_JOIN(0)',
name =>'TEST_DISABLE_HASHJOIN',
description => 'this is a test join hint.',
validate => true,
fuzzy = true
);

2.4 INJECT HINT设置查看

查询SYSINJECTHINT视图可以查看已指定的 SQL 语句和对应的 HINT:

select NAME, DESCRIPTION, VALIDATE, SQL_TEXT, HINT_TEXT, CREATOR, CRTDATE from SYSINJECTHINT;

2.5 INJECT HINT状态修改

使用SF_ALTER_HINT函数可以设置INJECT HINT无效,置为无效后,相关的sql hint将不再生效。

SF_ALTER_HINT('TESTJOIN' ,'STATUS', 'DISABLED');

2.6 INJECT HINT设置删除

SF_DEINJECT_HINT函数可以将设置INJECT hint删除。

sf_deinject_hint('TESTJOIN');

三、说明

HINT提示只能对单个sql修改设置HINT,SF_INJECT_HINT支持SQL模糊配置设置,两者都是针对SQL语句生效。

SQL语句模糊匹配时,执行的SQL语句必须与SF_INJECT_HINT规则中的SQL语句完全相同(包括SQL语句中的空格等)。指定的HINT对所有符合SQL语句均生效。

两种方法不仅可以设置SQL多表连接方法,索引提示,也可以设置INI参数提示(支持使用HINT的INI参数可通过V$HINT_INI_INFO 动态视图查询)、统计信息提示等,使SQL优化更灵活。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DB实践

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值