DM 查询优化器采用基于代价的方法。在估计代价时,主要以统计信息或者普遍的数据分布为依据。在大多数情况下,估计的代价都是准确的。但在一些比较特殊的场合,可能会生成很差的执行计划。如果现阶段不能很好的改写SQL或者及时收集准确的统计信息,那么就需要HINT出手了。HINT是达梦(DM)数据库中用于人工干预查询优化器的指令,通过特定语法嵌入SQL语句中,指导优化器生成指定的执行计划。其本质是“对优化器的手动约束”,不会改变SQL语义,但能强制优化器采用特定策略(如索引、连接顺序等),以解决自动优化不足的问题。
DM8的HINT 有以下类型:
优化查询性能
强制使用索引:当优化器未选择最优索引时,通过INDEX提示强制使用指定索引,减少全表扫描。
控制连接方式:通过USE_HASH、USE_NL等提示指定表连接算法(哈希连接、嵌套循环连接等),避免优化器选择高代价的连接路径。
并行查询控制:通过PARALLEL提示开启并行执行,加速大数据量查询。
解决特殊场景问题
统计信息不准确:当数据分布倾斜或统计信息过时时,优化器可能生成劣质计划,HINT可强制使用已知高效的执行路径。
复杂查询优化:在多表关联或子查询中,HINT可缩小优化器搜索空间,减少计划生成时间。
兼容性与迁移支持
在跨版本升级或异构数据库迁移(如Oracle→DM)时,通过HINT保持原执行计划一致性,避免性能回退。
语法格式
HINT通过SQL注释形式嵌入,支持两种语法:
简洁语法:表名 + INDEX + 索引名(如T1 INDEX IDX_T1_ID)。
标准注释语法:
sql/*+ HINT1 [HINT2...] */
-- 示例:强制使用索引并指定并行度
SELECT /*+ INDEX(T1, IDX_T1_ID) PARALLEL(4) */ * FROM T1 WHERE ID > 2011;
常用HINT类型
INDEX(表名, 索引名):强制使用指定索引。NO_INDEX(表名, 索引名):禁止使用指定索引。USE_HASH(T1, T2):强制表T1与T2使用哈希连接。USE_NL(T1, T2):强制表T1与T2使用嵌套循环连接。PARALLEL(n):开启并行查询,指定并行度为n。动态注入HINT(无需修改SQL)
通过系统函数
--注入HINT
SF_INJECT_HINT('sql语句', '参数名(参数值)', '规则名', null,TRUE,TRUE);
--对指定 SQL 撤回已增加的 HINT
SF_DEINJECT_HINT('规则名');
--修改已指定 HINT 的规则属性
SF_ALTER_HINT('('规则名', 'STATUS', 'DISABLED');
创建全局规则,将HINT与特定SQL绑定:
sql-- 开启Hint注入功能
SP_SET_PARA_VALUE(1, 'ENABLE_INJECT_HINT', 1);
-- 绑定Hint规则
SF_INJECT_HINT(
SQL_TEXT => 'SELECT * FROM T1 WHERE ID = 1;',
HINT_TEXT => 'NO_INDEX(T1, IDX_T1_ID)',
NAME => 'RULE_NO_INDEX',
DESCRIPTION => '禁止使用IDX_T1_ID索引',
VALIDATE => TRUE
);
EXPLAIN命令验证执行计划是否生效。PARALLEL(n)需根据服务器资源合理设置,过度并行可能导致资源争用。文章
阅读量
获赞
