注册
达梦数据库的HINT
专栏/技术分享/ 文章详情 /

达梦数据库的HINT

好好先生 2026/01/09 248 0 0
摘要

达梦数据库的HINT

一、DM8的HINT

DM 查询优化器采用基于代价的方法。在估计代价时,主要以统计信息或者普遍的数据分布为依据。在大多数情况下,估计的代价都是准确的。但在一些比较特殊的场合,可能会生成很差的执行计划。如果现阶段不能很好的改写SQL或者及时收集准确的统计信息,那么就需要HINT出手了。HINT是达梦(DM)数据库中用于人工干预查询优化器的指令,通过特定语法嵌入SQL语句中,指导优化器生成指定的执行计划。其本质是“对优化器的手动约束”,不会改变SQL语义,但能强制优化器采用特定策略(如索引、连接顺序等),以解决自动优化不足的问题。

DM8的HINT 有以下类型:

  • ini参数类
  • 索引类
  • 连接方法类
  • 连接顺序类
  • 统计信息类
  • MPP本地对象类
  • 忽略重复键值类
  • 禁用计划缓存类
  • DMDPC数据分发方式类
  • 分区表遍历操作符PLL类
  • 单节点登录类
  • 视图不替换sql记录类
  • DMDPC读写分离类

二、HINT的作用

  1. 优化查询性能

    强制使用索引:当优化器未选择最优索引时,通过INDEX提示强制使用指定索引,减少全表扫描。

    控制连接方式:通过USE_HASHUSE_NL等提示指定表连接算法(哈希连接、嵌套循环连接等),避免优化器选择高代价的连接路径。

    并行查询控制:通过PARALLEL提示开启并行执行,加速大数据量查询。

  2. 解决特殊场景问题

    统计信息不准确:当数据分布倾斜或统计信息过时时,优化器可能生成劣质计划,HINT可强制使用已知高效的执行路径。

    复杂查询优化:在多表关联或子查询中,HINT可缩小优化器搜索空间,减少计划生成时间。

  3. 兼容性与迁移支持

    在跨版本升级或异构数据库迁移(如Oracle→DM)时,通过HINT保持原执行计划一致性,避免性能回退。

三、HINT的原理

  1. 解析阶段剥离
    SQL解析器识别并剥离HINT注释,不将其视为标准语法的一部分。优化器在生成执行计划前,加载所有可用路径(如索引、连接顺序),并根据HINT指令调整选择逻辑。
  2. 执行计划生成
    优化器结合HINT指令(如强制索引、连接顺序)与代价模型,生成最终执行计划。若HINT无法实现(如指定索引不存在),则忽略并继续自动优化。
  3. 执行引擎运行
    优化器选定的执行计划交由执行引擎执行,HINT的影响仅限于计划生成阶段。

四、开启与使用方法

  1. 语法格式

    HINT通过SQL注释形式嵌入,支持两种语法:

    • 简洁语法表名 + INDEX + 索引名(如T1 INDEX IDX_T1_ID)。

    • 标准注释语法:

      sql/*+ HINT1 [HINT2...] */ -- 示例:强制使用索引并指定并行度 SELECT /*+ INDEX(T1, IDX_T1_ID) PARALLEL(4) */ * FROM T1 WHERE ID > 2011;
  2. 常用HINT类型

    • 索引提示:
      • INDEX(表名, 索引名):强制使用指定索引。
      • NO_INDEX(表名, 索引名):禁止使用指定索引。
    • 连接方法提示:
      • USE_HASH(T1, T2):强制表T1与T2使用哈希连接。
      • USE_NL(T1, T2):强制表T1与T2使用嵌套循环连接。
    • 并行提示:
      • PARALLEL(n):开启并行查询,指定并行度为n。
  3. 动态注入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 );

五、使用注意事项

  1. INI 参数 ENABLE_INJECT_HINT 需设置为 1;
  2. SQL 只能是语法正确的增删改查语句。
  3. HINT 一指定,则全局生效。
  4. 系统检查 SQL 匹配时,必须是整条语句完全匹配,不能是语句中子查询匹配。
  5. SQL 会经过系统格式化,格式化之后的 SQL 和指定的规则名称必须全局唯一。
  6. 语法正确性
    • HINT语法错误或参数无效时,DM不会报错,而是直接忽略。需通过EXPLAIN命令验证执行计划是否生效。
  7. 性能权衡
    • Hint是“硬编码”优化,可能因数据分布变化(如表结构修改、索引删除)导致性能下降。需定期审计带Hint的SQL,确保其仍符合最新统计与负载情况。
  8. 版本兼容性
    • 不同DM版本支持的HINT语法可能不同,升级后需测试hint的兼容性。
  9. 避免过度依赖
    • 优先优化SQL写法(如添加合适索引、简化查询逻辑),仅在自动优化不足时使用hint。
  10. 复杂查询限制
    • 在多表关联或子查询中,Hint可能因表别名、索引名错误或连接顺序矛盾被忽略。需确保Hint中的表名与SQL中一致(若使用别名,hint中需指定别名)。
  11. 并行度设置
    • 并行提示PARALLEL(n)需根据服务器资源合理设置,过度并行可能导致资源争用。
评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服