当一张表同时拥有行存储和列存储两种组织方式时,查询优化器通常只会选择其中一种访问路径,要么扫描行存储部分,要么扫描列存储部分。但实际上很多分析查询只需要少数几列,而事务查询需要完整行,如果优化器能够根据查询需求在行存储和列存储之间智能切换,甚至在同一查询计划中混合使用,就能显著提升整体吞吐量。DB2从较新版本开始引入了opt_enable_partial_mixed优化器参数,用于控制是否允许生成部分混合存储的访问计划。

这个参数本质上是一个布尔开关,取值为YES或NO。默认情况下,DB2的优化器倾向于保守策略,只会单独使用行存储索引或列存储向量化扫描,不会在一个计划中同时引用两种存储特性。启用opt_enable_partial_mixed之后,优化器会额外考虑一种可能性:对于同一个表,在查询的不同谓词或不同阶段,分别利用行存储索引和列存储筛选,最后将结果合并。例如一个表有一个行存储的唯一索引用于点查,同时列存储部分又有适合分析扫描的压缩列,启用该参数后优化器可能会生成先通过行索引定位范围,再对列存储部分进行向量化聚合的计划。
部分混合存储的工作机制
要理解这个参数,首先需要明确DB2中的混合存储表结构。在DB2中,可以通过CREATE TABLE语句指定某些列使用列式存储,另一些列使用行式存储,或者对整个表进行行存储,同时创建列式组织的投影(projection)。例如使用ORGANIZE BY COLUMN子句创建列式表后,再为它添加行存储的索引,或者使用CREATE TABLE ... ORGANIZE BY ROW后通过物化查询表(MQT)建立列式副本。
当优化器面对一张混合存储表时,如果opt_enable_partial_mixed为NO,它会将表视为纯行存储或纯列存储,具体取决于表的基表组织方式。如果基表是行存储,那么即使存在列式投影,优化器也可能忽略它;反之亦然。而启用该参数后,优化器会将行存储索引和列存储投影都纳入候选访问路径,并尝试构造“行列混合”的执行计划。
这种混合计划在内部实现上通常表现为两个阶段:第一阶段利用行存储索引快速过滤出满足某些等值或范围条件的记录标识(RID),第二阶段将这些RID传递给列存储扫描算子,只对相关行进行列式读取和聚合。这样既保留了行索引在点查和范围扫描上的低延迟优势,又利用了列存储在分析聚合时的高带宽和压缩特性。
如何启用opt_enable_partial_mixed
启用该参数可以在数据库级别、会话级别或语句级别进行设置。最常用的是数据库级别配置,通过UPDATE DB CFG命令修改数据库配置参数,然后重新激活数据库使其生效。不过需要注意的是,并非所有DB2版本和平台都支持该参数,它主要出现在支持混合存储的企业版或高级版中。执行以下命令可以查看当前数据库是否支持该参数:
SELECT name, value, default_value, isdefault FROM SYSIBMADM.DBCFG WHERE name = 'opt_enable_partial_mixed';
如果查询结果为空,说明当前版本不支持该参数。如果存在该参数,通常默认值为NO。可以在数据库级别将其设置为YES:
UPDATE DB CFG FOR sample USING opt_enable_partial_mixed YES; DEACTIVATE DATABASE sample; ACTIVATE DATABASE sample;
如果需要只在特定会话中启用,可以使用SET CURRENT QUERY OPTIMIZATION或者SET CURRENT REFRESH AGE类似的会话级命令吗?其实更直接的是通过SET CURRENT EXPLAIN MODE无法改变优化器参数。正确做法是使用SET CURRENT QUERY OPTIMIZATION = 9并不影响此参数。DB2提供了一种会话级设置优化器参数的方式:通过CALL SYSPROC.ADMIN_SET_INT_PARAM或直接使用SET CURRENT QUERY ACCELERATION?实际上,opt_enable_partial_mixed属于优化器配置参数,可以在会话中使用SET CURRENT QUERY OPTIMIZATION吗?官方文档指出,该参数可以通过SET CURRENT DEGREE类似的语句修改,但更标准的方法是使用UPDATE DB CFG全局设置,或在连接属性中设置。有些版本支持SET SESSION AUTHORIZATION不影响。为保险起见,推荐使用数据库级别配置,因为它对所有会话生效。如果只需要测试,可以在会话中通过SET CURRENT CLIENT_USERID等无关命令不行。
实际上,DB2提供了一个通用的会话级设置接口:使用SET CURRENT QUERY OPTIMIZATION可以设置优化级别,但无法直接开启该开关。有一种方法是在连接字符串或CLI配置中指定。对于开发测试,可以临时修改数据库配置后重启。在应用程序中,可以通过JDBC或CLI连接属性optEnablePartialMixed来设置。例如在Java中使用如下代码:
Properties props = new Properties();
props.setProperty("user", "db2admin");
props.setProperty("password", "secret");
props.setProperty("optEnablePartialMixed", "true");
Connection conn = DriverManager.getConnection("jdbc:db2://localhost:50000/sample", props);
这样会在该连接会话中启用部分混合存储,无需修改全局数据库配置。
实际效果与注意事项
启用opt_enable_partial_mixed并不总是能带来性能提升。优化器会评估混合计划的代价,只有当混合计划的估算成本低于纯行计划或纯列计划时才会采用。这意味着如果表的数据量较小,或者查询本身只需要访问很少的列或很少的行,混合计划可能因为额外的RID传递和计划复杂度而变得更慢。因此在启用该参数之前,应当对典型工作负载进行基准测试,并观察执行计划的改变。
可以使用db2expln或db2exfmt工具查看启用前后的访问计划。重点关注是否出现了同时包含行存储索引扫描和列存储扫描的算子,例如HSJOIN或FETCH与CTQ的组合。启用后,优化器可能更倾向于使用行索引进行预过滤,然后将结果交给列存储引擎进行聚合。这种计划在OLAP查询中尤为常见。
另外,需要留意该参数与opt_direct_access_columnar、opt_mixed_index等其他优化器参数的相互作用。通常建议在启用opt_enable_partial_mixed的同时,确保opt_direct_access_columnar也为YES,否则列存储部分可能无法被直接访问。不同DB2版本对这些参数的默认值和依赖关系有所不同,应当查阅对应版本的官方文档。
还有一个常见误区:认为只要创建了列式投影,DB2就会自动使用混合存储。实际上,混合存储的自动使用受多个因素制约,包括表的统计信息是否及时更新、投影是否被注册为优化器可见、以及参数开关是否打开。因此,启用参数后需要执行RUNSTATS命令更新统计信息,并确保列式投影的自动刷新机制正常工作。
总结来说,opt_enable_partial_mixed是DB2混合存储能力的重要控制开关,适合在既有事务处理又有分析查询的混合负载环境中启用。通过合理配置和测试,可以在不牺牲事务性能的前提下,显著加速分析型SQL的执行效率。
DB2 opt_enable_partial_mixed部分混合存储优化器参数修改时间:2026-08-27 05:26:48