在 DB2 优化器生成执行计划时,基数估计是决定访问路径质量的核心环节。opt_enable_partial_data_testing 这个参数控制优化器是否可以在缺少完整统计信息或谓词复杂度较高时,对表或索引的部分数据页进行试探性读取,从而验证过滤条件实际的选择度。它的本质是在全表扫描和纯统计估算之间提供一种折中方案,让优化器有机会用很小的读取成本换取更准确的执行计划。

一、opt_enable_partial_data_testing 解决什么问题
优化器在决定使用索引扫描、全表扫描还是表连接顺序时,高度依赖过滤条件的选择度估算。当表上缺少 RUNSTATS 统计信息,或者过滤条件包含函数、表达式、LIKE 中缀匹配、跨列比较时,DB2 往往只能采用默认过滤因子或经验值进行估算。例如,一个字符串列使用 LIKE 条件且通配符出现在开头,如果没有统计信息,优化器可能直接使用 10% 甚至更高的默认选择率,实际数据可能只有万分之一。这种偏差会让优化器选择错误的索引,或者在全表扫描和索引回表之间做出不合理的判断。
opt_enable_partial_data_testing 开启后,优化器可以在查询硬编译阶段针对候选表或索引发起受限扫描。所谓受限扫描,是指只读取表或索引头部、采样页或部分数据块,而不是扫描整张表。优化器从这些实际数据中计算匹配行的比例,再结合已有统计信息修正过滤因子。因为读取量通常远小于全表扫描,编译开销相对可控,但获得的信息比盲目猜测要准确得多。
该参数属于优化器相关的注册表变量,默认情况下通常为关闭状态。关闭时优化器只使用统计信息或默认值;开启后符合条件的查询会在编译阶段多一步数据采样。它并不修改统计信息,也不影响 RUNSTATS 生成的内容,只是在生成执行计划前临时读取部分数据。因此它与统计信息收集是互补关系,而不是替代关系。
二、如何启用并验证参数是否生效
启用 opt_enable_partial_data_testing 需要在实例级别通过 db2set 命令设置注册表变量。由于该参数属于实例级配置,设置后必须重启 DB2 实例才能让所有数据库会话看到新的取值。下面是一套标准的启用与验证命令。
db2set DB2_OPT_ENABLE_PARTIAL_DATA_TESTING=YES db2set -all db2stop db2start
执行 db2set -all 后,如果输出中出现了 DB2_OPT_ENABLE_PARTIAL_DATA_TESTING=YES,说明变量已经写入实例注册表。需要强调的是,仅执行 db2set 并不会立即影响正在运行的会话,必须重启实例。如果不想重启整个实例,可以在测试环境使用独立的测试实例验证,或安排变更窗口,避免对在线业务造成影响。
验证参数是否真正影响查询,不能只看注册表变量。因为 SQL 可能命中包缓存,或者该查询在关闭状态下已经生成过执行计划。建议使用 db2expln 或 db2exfmt 检查开启前后的访问计划。重点关注输出中的基数估计、连接方式、索引使用情况。对于动态 SQL,可以使用 db2pd -db sample -dynamic 查看当前数据库的动态 SQL 编译情况,确认硬编译是否重新发生。也可以使用 db2 flush package cache dynamic 清空包缓存后重新执行目标 SQL,以强制生成新计划。
三、典型应用场景与性能收益
在数据仓库和报表系统中,这类参数的价值最为明显。报表查询通常涉及大表连接、范围过滤、分组聚合,且很多表要么统计信息滞后,要么临时表完全没有统计信息。以一个订单明细表为例,按订单状态和下单日期做过滤,然后与客户表连接。如果订单状态列存在明显的数据倾斜,已完成订单占 80%,待支付只占 2%,而默认统计信息因为收集时间较早,认为待支付比例为 15%。优化器很可能高估待支付订单的返回行数,从而选择全表扫描和哈希连接;但如果高估方向反了,也可能低估大结果集而选择嵌套循环。开启部分数据测试后,优化器会读取少量数据页验证状态列的实际占比,有机会纠正连接方式和访问路径。
复杂谓词是另一个典型场景。比如对日期列使用函数截取、对字符串列使用正则或 LIKE 模糊匹配、对多列做算术比较,这些条件很难通过直方图或列统计信息准确估算。部分数据测试可以直接观察采样页中的行满足条件的比例,对这类谓词尤其有效。对于包含视图嵌套、派生表、CTE 的查询,优化器需要跨层传递选择度,参数可以在中间结果上做进一步验证,减少错误累积。
不过性能收益并不是无条件的。该参数增加的是硬编译阶段的 I/O 和 CPU 消耗。如果一个 SQL 只执行一次,采样数据带来的编译开销可能会抵消执行阶段的收益;如果同一个 SQL 反复执行且每次都必须硬编译,编译开销会被放大。因此高并发 OLTP 环境需要谨慎评估。建议对核心业务 SQL 使用包或存储过程固定执行计划,降低硬编译频率。对于批处理任务和即席查询,则可以大胆开启并对比执行时间。
四、使用限制与常见问题排查
opt_enable_partial_data_testing 不能替代 RUNSTATS。它只是在查询编译时对少量数据进行采样,采样范围有限,无法覆盖整张表的统计特征。如果表的数据分布极为分散,或者采样页不能代表整体数据,参数也可能给出错误提示。生产环境仍然需要定期收集统计信息,特别是对大表执行 RUNSTATS 时使用抽样或列组统计,保持基础元数据的新鲜度。参数更像是统计信息失效时的一道补丁,而不是长期依赖的机制。
启用后如果发现查询性能没有提升,反而编译时间明显增加,可以从以下几个方面排查。首先确认参数是否真的生效:执行 db2set -all 并检查实例已经重启。其次查看 SQL 是否命中了旧的包缓存:使用 db2 flush package cache dynamic 后再执行。再次检查目标查询是否包含优化器无法采样的结构,例如远程表、MQT 或某些内部函数。最后通过 db2exfmt 对比开启前后的执行计划,如果访问路径没有变化,说明该查询的基数估计可能不是性能瓶颈,需要从索引设计、统计信息、SQL 写法等方向继续优化。
还可以结合 DB2 优化级别参数进行测试。优化级别会影响优化器对部分数据测试的使用程度,但具体行为依赖版本和查询复杂度。不建议在不了解工作负载的情况下开启一系列 DB2_OPT 参数,应该一次只调整一个变量,观察系统整体表现。对于采样带来的编译时间波动,可以通过监控包缓存、动态 SQL 编译时间和平均执行时间,判断是否适合长期开启。
DB2opt_enable_partial_data_testing部分数据测试修改时间:2026-08-22 02:20:04