帮你快速理解、总结文档立即下载

Runtime Filter

最近更新时间:2026-08-20 15:23:31
我的收藏

概述

Runtime Filter(运行时过滤器)是 TDSQL Boundless 内核在查询执行阶段动态生成过滤条件的优化能力,用于减少 Hash Join 场景下的数据扫描量。
Hash Join 的匹配过程分为两个阶段:使用较小的一侧构建哈希表(Build 侧),再用另一侧的数据探测该哈希表(Probe 侧)。如果 Probe 侧某些 Join Key 的取值在 Build 侧构建的哈希表中不存在,这些数据必然不会出现在最终结果中。Runtime Filter 利用这一特点,在 Build 侧构建完成后,根据其数据生成一个轻量的过滤器,下推到 Probe 侧的存储引擎,在读表过程中提前过滤掉不满足条件的数据,从而减少 Probe 侧的扫描量、网络传输量以及 Hash Join 的计算量。
该能力尤其适合大表(事实表)与小表(维度表)做等值 Join 的场景:维度表过滤后命中的数据量越小,事实表能够提前过滤掉的数据就越多,性能提升越明显。

支持版本

适用于 TDSQL Boundless V21.6.4.0 及以上版本。

工作原理

过滤器类型

TDSQL Boundless 目前仅支持布隆过滤器(Bloom Filter)类型的 Runtime Filter。布隆过滤器根据 Build 侧数据估算的唯一值数量(NDV)动态调整大小,判断结果只会存在极小概率的误判(即可能将本应过滤的数据误判为需要保留,但不会漏判应保留的数据)。

生效条件

Runtime Filter 在查询规划阶段自动判定是否生效,需要同时满足以下条件:
使用 Hash Join,且 Join 类型为内连接(Inner Join)或半连接(Semi Join),不支持左外连接(Left Join)、全外连接(Full Outer Join)与反连接(Anti Join)。这些 Join 类型不会提前丢弃未匹配的数据,无法安全应用提前过滤。
Join 条件中存在等值比较,且等值比较不能是复合行值(Row)比较,也不能使用自定义取值方式的复杂比较表达式。
Probe 侧只涉及一张表,该表的存储引擎为 RocksDB(TDStore),且不是临时表;表扫描方式为全表扫描、索引扫描或基于索引的 REF/EQ_REF 等常见访问路径。
Probe 侧预估的扫描行数达到一定规模,且预估的过滤效果(Build 侧唯一值数量相对 Probe 侧扫描行数的比例)达到一定阈值,即预计能过滤掉相当比例(默认约一半以上)的 Probe 侧数据时才会启用,避免额外计算开销超过收益。
布隆过滤器预估占用的内存不超过参数 runtime_bloom_filter_max_size 设置的上限。

自适应调整

构建布隆过滤器的过程中,如果实际插入的唯一值数量与规划阶段的预估值偏差过大(远超预估),内核会提前停止继续构建,避免过滤器结果失真;在探测阶段,如果发现过滤效果已明显低于预期,也会放弃继续下推该过滤器,避免影响正常查询性能。

支持版本

适用于 TDSQL Boundless V21.6.4.0 及以上版本。

使用限制

Runtime Filter 默认关闭,需要开启参数 optimizer_switch 中的 join_runtime_filter 开关后才会生效。
仅支持 SELECT 语句,且需要在无锁的快照读事务中执行;LOCK TABLES 模式,以及存在跨节点参与者的显式加锁事务下不生效。
每次 Hash Join 只支持对其中一个 Probe 表生效,暂不支持同时对多张表下推过滤条件。
Probe 侧表的存储引擎必须为 RocksDB(TDStore),临时表、其他存储引擎的表不支持。

使用说明

开启 Runtime Filter

Runtime Filter 通过 optimizer_switch 系统变量中的 join_runtime_filter 开关控制,默认关闭。执行以下语句开启:
SET SESSION optimizer_switch = 'join_runtime_filter=on';

查看 Runtime Filter 是否生效

开启后,可以通过 EXPLAIN 查看 Runtime Filter 的生效情况。例如以下 Join 查询:
EXPLAIN SELECT STRAIGHT_JOIN * FROM t1 JOIN t2 ON t1.a = t2.a;
在传统格式的 EXPLAIN 结果中,Extra 列会显示 Using join runtime filter (字段列表)
1 SIMPLE t1 ... NULL
1 SIMPLE t2 ... Using where; Using join runtime filter (`test`.`t2`.`a`); Using join buffer (hash join)
EXPLAIN format=tree 结果中,Hash Join 节点会显示 with join runtime filter: bloom(字段列表)
-> Inner hash join (t2.a = t1.a) with join runtime filter: bloom(t2.a)
-> Table scan on t2
-> Hash
如果 Runtime Filter 未生效,可以通过查询优化器跟踪信息(Optimizer Trace)查看具体原因:
SET optimizer_trace = "enabled=on";
SELECT STRAIGHT_JOIN * FROM t1 JOIN t2 ON t1.a = t2.a;
SELECT json_extract(trace, "$.steps[*].join_optimization.steps[*].runtime_filter_optimize")
FROM information_schema.optimizer_trace;
未生效时会返回类似如下信息,其中 cause 字段说明具体原因:
[{"cause": "runtime filter only supports probe table in rocksdb", "enable_runtime_filter": false}]

使用 Hint 控制 Runtime Filter

除了通过 optimizer_switch 全局控制外,还可以使用 Hint 在单条语句中按表精确控制 Runtime Filter 的启用与禁用:
-- 强制在 t2 上启用 Runtime Filter(跳过效果评估)
SELECT /*+ JOIN_RUNTIME_FILTER(t2) */ STRAIGHT_JOIN * FROM t1 JOIN t2 ON t1.a = t2.a;

-- 禁止在 t2 上使用 Runtime Filter
SELECT /*+ NO_JOIN_RUNTIME_FILTER(t2) */ STRAIGHT_JOIN * FROM t1 JOIN t2 ON t1.a = t2.a;

-- 不指定表名,对语句中所有符合条件的 Join 生效
SELECT /*+ JOIN_RUNTIME_FILTER() */ STRAIGHT_JOIN * FROM t1 JOIN t2 ON t1.a = t2.a;
说明:
Hint 中可以在表名后追加过滤器类型 BLOOM_FILTER(当前只支持该类型),例如 /*+ JOIN_RUNTIME_FILTER(t2 BLOOM_FILTER) */,效果与不指定类型时相同。

相关参数

参数名
作用域
默认值
取值范围
说明
optimizer_switch 中的 join_runtime_filter
SESSION
off
on、off
是否开启 Runtime Filter。
runtime_bloom_filter_max_size
SESSION
64
0 - 128
布隆过滤器占用内存的上限,单位为 MB,取值为0表示禁用该功能。过滤器占用内存与 Build 侧数据估算的唯一值数量相关,例如1MB约对应100万唯一值,16MB约对应1000万唯一值,默认值64MB约对应8000万唯一值。