DB2优化器的核心任务之一是为每一条SQL语句选择成本最低的访问路径,而成本估算的准确性高度依赖于对中间结果集大小的预测。过滤因子(Filter Factor)就是描述一个谓词能够保留多少比例行的数值,它是选择性(Selectivity)的另一种表达形式。例如,如果一个表有100万行,某个谓词的过滤因子为0.01,意味着优化器预计只有1万行满足该条件。这个数值直接影响索引扫描的收益判断、排序与哈希连接的可行性以及表连接的驱动顺序。

在DB2中,过滤因子的估算并非凭空产生,而是建立在统计信息基础上的数学模型。当用户执行RUNSTATS命令收集统计信息后,系统目录中会保存列基数(COLCARD)、高频值(HIGH2KEY)、分位数(QUANTILES)以及频率分布等信息。优化器在编译查询时,会读取这些统计信息,根据谓词类型选择对应的公式计算过滤因子。如果统计信息缺失或过期,DB2会利用默认假设,例如等值谓词的过滤因子默认为1/COLCARD,若连COLCARD都没有,则可能假设为1/25或使用一个保守的固定值,这常常会导致错误的计划选择。
过滤因子的概念与作用
过滤因子本质上是谓词选择性的度量,定义为满足谓词的行数占总行数的比例。它的取值范围在0到1之间,数值越小表示过滤性越强,即能够去除更多的行。优化器使用过滤因子来估计中间结果集的大小,而这个估计值又作为输入参与下一阶段的成本计算。例如,在访问单个表时,如果索引扫描的成本与过滤因子密切相关:过滤因子小,索引扫描只需要访问少量数据页,成本较低;过滤因子大,全表扫描可能更高效。在多表连接时,过滤因子决定了表的连接顺序——通常先处理过滤性强的表,以减少后续连接操作的行数。
DB2优化器在访问计划中会显示每个操作符的输出行数估计,这个估计就是通过累计应用过滤因子得到的。例如,一个表扫描操作符后跟一个过滤操作符,过滤操作符的估计输出行数等于输入行数乘以该谓词的过滤因子。在EXPLAIN输出中,我们可以看到每个步骤的基数(Cardinality),这些基数的准确性直接依赖于过滤因子的准确性。因此,理解过滤因子如何计算,对于分析执行计划偏差、定位性能问题至关重要。
过滤因子的另一个重要作用是帮助优化器判断是否值得使用索引。如果谓词的过滤因子很小(例如小于0.1),索引扫描往往能显著减少I/O,优化器倾向于使用该索引;反之,如果过滤因子接近1,索引扫描几乎需要访问所有数据页,还要付出额外的索引页访问开销,全表扫描会更合适。此外,对于星型模式的雪花查询,过滤因子的估算会通过连接谓词传递,影响维度表过滤后事实表扫描范围的估计,进而影响是否选择位图索引或星型连接方案。
DB2过滤因子的计算方法
DB2对不同类型的谓词使用不同的过滤因子计算公式。对于等值谓词(col = constant),基本过滤因子为1/COLCARD,其中COLCARD是列的不同值数量。但若存在高频值统计,优化器会检查该常量是否属于高频值,如果是,则过滤因子直接取该高频值的频率(FREQUENCY);如果不是,则剩余部分按照均匀分布计算。例如,某列有100个不同值,其中值'A'出现频率为0.3,那么col = 'A'的过滤因子为0.3,而col = 'B'(非高频值)的过滤因子为(1-0.3)/(100-1)≈0.00707。
范围谓词(col > constant、col < constant、col BETWEEN constant1 AND constant2)的过滤因子基于列的最小值、最大值和分布统计计算。如果只收集了基本统计信息,优化器假设数据在最小值和最大值之间均匀分布,那么col > x的过滤因子为(max_val - x)/(max_val - min_val)。但真实数据往往倾斜,因此RUNSTATS允许收集分位数(QUANTILES)和柱状图(HISTOGRAM),优化器可以通过插值估算更准确的比例。例如,如果收集了20个分位数,优化器会定位constant所在的分位区间,按线性分布估算过滤因子。此外,范围谓词还可以利用频率统计,如果范围刚好覆盖部分高频值,计算会更加精细。
LIKE谓词的过滤因子处理更为复杂。对于col LIKE 'pattern%'的形式,如果模式以通配符开头(如%abc),则无法使用索引且过滤因子通常被估算为一个固定小值,例如0.1(具体取决于DB2版本和参数设置)。如果模式以常量开头(如'abc%'),DB2会尝试利用索引的键值分布来估算,类似于范围扫描。对于包含多个谓词的组合条件,DB2默认假设谓词之间相互独立,将单个过滤因子相乘得到组合过滤因子。但这种独立性假设在列之间存在相关性时会产生较大误差,DB2允许通过收集列组统计信息(COLGROUP)来改善相关列的组合过滤因子估算。
观察和调整opt_filter_factor
opt_filter_factor这个名称在部分DB2环境或第三方监控工具中常被用来指代优化器实际使用的过滤因子值。要在DB2中观察过滤因子,最常见的方法是使用db2exfmt工具格式化EXPLAIN输出。在访问计划的详细部分,每个操作符会显示累积的过滤因子或谓词选择性信息。另外,通过查询EXPLAIN表(如EXPLAIN_INSTANCE、EXPLAIN_STREAM、EXPLAIN_OPERATOR等)也可以获取每个操作符的基数估计,反推过滤因子。在较新的DB2版本中,可以使用SYSPROC.EXPLAIN_GET_MSGS或存储过程输出优化器诊断信息,其中包含详细的谓词选择性计算过程。
如果发现过滤因子估算严重偏离实际,可以通过重新收集统计信息改善。RUNSTATS命令应使用较高的采样率和详细的分布选项,例如:RUNSTATS ON TABLE schema.table WITH DISTRIBUTION AND DETAILED INDEXES ALL。对于列之间相关性强的场景,应创建列组统计信息:RUNSTATS ON TABLE schema.table ON COLUMNS ((col1, col2))。此外,DB2允许通过优化概要(Optimization Profile)手动指定谓词的过滤因子,使用SQL语句SET CURRENT OPTIMIZATION PROFILE加载XML格式的概要文件,其中可以定义FILTER FACTOR元素来覆盖默认估算。这是一种强大的调优手段,但需要谨慎使用,因为错误的设定可能导致更坏的执行计划。
DB2也提供了一些注册表变量影响过滤因子的计算偏置,例如DB2_OPT_FILTER_FACTOR在某些版本中可能控制选择性估算的保守程度。虽然官方文档中不一定直接出现这个变量名,但类似功能的参数如DB2_SELECTIVITY、DB2_INLIST_TO_NLJN等会影响特定情况下的过滤因子。DBA可以通过调整这些参数来纠正系统性的估算偏差。不过,最好的实践仍然是保持统计信息的新鲜度和完整性,确保优化器有足够的数据做出准确判断。定期执行RUNSTATS、监控数据分布变化、利用自动统计信息收集功能,都是维持过滤因子准确性的有效方法。
影响过滤因子准确性的关键因素
统计信息的陈旧度是影响过滤因子准确性的首要因素。如果表的数据发生了大量插入、更新或删除,但RUNSTATS没有及时重新执行,COLCARD、HIGH2KEY等目录统计信息就会偏离实际。例如,一个原本只有10个不同值的列现在有了1000个不同值,但COLCARD仍然是10,等值谓词的过滤因子会被高估10倍,导致优化器错误地选择索引扫描。因此,在数据变更超过一定比例后,应及时收集统计信息。DB2支持自动RUNSTATS,可以通过数据库配置参数AUTO_RUNSTATS启用,让系统在后台自动更新变化较大的表的统计信息。
数据分布的倾斜程度也直接挑战过滤因子的计算公式。均匀分布假设在倾斜数据下完全失效,这也是为什么必须收集分布统计(DISTRIBUTION)。分布统计包括频率统计和分位数,能够捕捉高频值和数据分布的转折点。对于高度倾斜的列,例如某个状态码99%的行都是'ACTIVE',那么col = 'ACTIVE'的过滤因子应该是0.99而不是1/不同值数。如果没有频率统计,优化器会严重低估该谓词的选择性,可能选择全表扫描而放弃索引,或者错误地调整连接顺序。因此,对关键过滤列收集完整的分布统计至关重要。
多列之间的相关性同样会破坏过滤因子相乘的独立性假设。假设WHERE条件同时包含city = 'Beijing'和country = 'China',这两个谓词高度相关:满足city = 'Beijing'的行几乎都满足country = 'China'。优化器如果分别计算两个过滤因子再相乘,会得到一个过小的组合过滤因子,低估结果集大小。解决方法是收集列组统计信息,让优化器知道这两列的组合基数。DB2的RUNSTATS支持ON COLUMNS子句指定列组,优化器在计算组合谓词过滤因子时会使用列组基数。此外,对于连接谓词,过滤因子还会受到连接键分布的影响,统计信息中的连接基数(JOIN CARD)也有助于改善多表连接时的过滤因子估算。
DB2优化器过滤因子opt_filter_factor修改时间:2026-08-24 04:09:16