
好的,我将为您全面深入地解析 Oracle 19C 数据库中的 V$SQL_JOIN_FILTER 动态性能视图。这个视图是诊断和理解 Oracle 一项重要性能优化技术——连接过滤(Join Filtering),特别是 Bloom Filter 的关键。
🔍 Oracle 19C V$SQL_JOIN_FILTER 动态性能视图详解
1️⃣ 视图概述与核心作用
V$SQL_JOIN_FILTER 动态性能视图提供了关于 SQL 语句执行过程中所使用的连接过滤器(Join Filter)的实时统计信息。
连接过滤(最常用的是 Bloom Filter)是 Oracle 优化器在处理哈希连接(Hash Join)或并行查询时,用于显著减少参与连接的数据量、降低 I/O 和 CPU 开销的一种高级优化技术。
该视图的核心作用在于:
- 性能诊断:确认优化器是否在关键查询中使用了连接过滤优化。
- 效果评估:量化过滤器的效率,例如查看它过滤掉了多少条不必要的记录。
- 问题排查:识别过滤器效率低下(过滤效果差)的情况,这可能成为 SQL 调优的切入点。
- 理解执行计划:将执行计划中的
JOIN FILTER CREATE和JOIN FILTER USE操作与具体的运行时统计数据关联起来。
2️⃣ 字段详细含义
V$SQL_JOIN_FILTER 视图中的每个字段都揭示了连接过滤器生命周期中的一个方面。以下是其字段的详细解释:
| 字段名称 | 数据类型 | 含义说明 |
|---|---|---|
| SQL_ID | VARCHAR2(13) | 正在使用连接过滤器的 SQL 语句的唯一标识符。这是与 V$SQL、V$SQLAREA、V$SQL_PLAN 等视图进行关联的关键字段。 |
| CHILD_NUMBER | NUMBER | 子游标编号。与 SQL_ID 共同唯一标识一个具体的子游标执行计划。同一个 SQL_ID 可能因环境变化(如绑定变量窥视)而有多个不同的执行计划(子游标)。 |
| FILTER_ID | NUMBER | 过滤器的唯一标识符。在一个 SQL 语句的执行计划中,可能会创建多个连接过滤器,此 ID 用于区分它们。 |
| ACTIVE | VARCHAR2(1) | 指示过滤器当前是否处于活动状态。典型值为 Y 或 N。主要用于实时监控并行查询的执行过程。 |
| BLOCKED | VARCHAR2(1) | 指示过滤器的消费者(USER)是否正在等待生产者(CREATOR)构建完成过滤器。典型值为 Y 或 N。用于诊断并行查询中的负载均衡问题。 |
| PROBED | NUMBER | 探测(Probe)次数。表示有多少条记录被使用过滤器(JOIN FILTER USE) 的表(通常是较大的表)拿去与过滤器进行匹配检查。 |
| FILTERED | NUMBER | 过滤掉的记录数。这是核心效能指标。表示有多少条记录因未能通过过滤器匹配而被提前丢弃,无需继续参与后续的更耗资源的连接操作。 |
| MAX_FILTERED | NUMBER | 单次过滤操作中过滤掉的最大记录数。 |
| MIN_FILTERED | NUMBER | 单次过滤操作中过滤掉的最小记录数。 |
| LAST_PROBED | DATE | 最后一次探测操作的时间戳。 |
| CON_ID | NUMBER | 容器 ID。在多租户环境(CDB)中,此字段标识该行信息所属的容器。值为 0 表示该行数据属于 CDB$ROOT(根容器)。 |
核心效能计算:
过滤效率(Filter Efficiency) = FILTERED / PROBED * 100%
这个比率越高,说明连接过滤器的效果越好,丢弃的无用数据越多,性能提升越显著。
3️⃣ 相关视图与基表
3.1 核心相关视图
V$SQL/V$SQLAREA:提供 SQL 语句的总体执行统计信息(执行次数、CPU 时间、磁盘读取等)。通过SQL_ID和CHILD_NUMBER与V$SQL_JOIN_FILTER关联,可以获取使用过滤器的 SQL 的完整性能画像。V$SQL_PLAN:这是最重要的关联视图。执行计划中会明确显示JOIN FILTER CREATE和JOIN FILTER USE操作步骤。V$SQL_PLAN中的FILTER_ID与V$SQL_JOIN_FILTER中的FILTER_ID直接对应。-- 查找执行计划中的连接过滤器操作 SELECT sql_id, child_number, id, operation, options, object_name, filter_id FROM v$sql_plan WHERE operation LIKE '%JOIN FILTER%' AND sql_id = '&target_sql_id';V$SQL_EXECUTION(或GV$SQL_EXECUTION用于并行):提供 SQL 执行的详细步骤信息,对于深入分析并行查询中过滤器的执行顺序和耗时非常有帮助。DBA_HIST_SQL_PLAN/DBA_HIST_SQLSTAT:AWR 历史快照中的对应视图,用于对过去的 SQL 执行进行历史回溯分析。
3.2 底层基表
V$SQL_JOIN_FILTER 是一个动态性能视图,其数据来源于 Oracle 实例运行时在内存中维护的统计信息。其底层基表是 X$QESQLJOINF。
重要说明:
X$QESQLJOINF是一个内部 X$ 表,存储了连接过滤器实时统计的原始数据。- 直接查询 X$ 表需要
SYS等极高权限,其结构未公开、不稳定且不受官方支持,绝不建议在生产环境中直接查询。 - 所有诊断和监控都应通过公开的、稳定的
V$SQL_JOIN_FILTER视图进行。
4️⃣ 底层原理与机制
4.1 什么是 Bloom Filter?
连接过滤的核心是一种称为 Bloom Filter 的概率型数据结构。
- 工作原理:它使用一个位数组(Bit Array)和一组哈希函数。首先将连接键(Join Key)通过哈希函数映射到位数组的某些位上,并将其置为
1。探测时,用同样的哈希函数检查探测键对应的位是否都为1。如果有任何一位为0,则该键肯定不存在于构建端集合中;如果所有位都是1,则该键很可能存在(存在一定的误判概率,但绝不会漏判)。 - 空间效率极高:Bloom Filter 的优点是占用内存极小,却能高效表示一个大型集合的成员信息。
4.2 连接过滤的工作流程(以哈希连接为例)
-
构建阶段(Build Phase / CREATE):
- 优化器选择将连接操作中较小的表(或结果集)作为构建端。
- 数据库进程(通常是查询协调器或并行从属进程)读取构建端的连接键。
- 根据这些键构建一个 Bloom Filter(
JOIN FILTER CREATE出现在执行计划中)。 - 这个过滤器本质上是一个“摘要”,代表了构建端所有连接键的集合。
-
探测阶段(Probe Phase / USE):
- 较大的表(探测端)在正式与构建端进行哈希连接之前,会先使用这个 Bloom Filter 进行预处理。
- 对于探测端的每一行,提取其连接键,并用过滤器进行检查(
JOIN FILTER USE出现在执行计划中)。 - 如果过滤器返回“肯定不存在”(这是 Bloom Filter 的核心优势),则该行会被立即丢弃,
V$SQL_JOIN_FILTER.FILTERED计数器增加。这避免了为这行数据执行昂贵的哈希计算和探测操作。 - 如果过滤器返回“可能存在”,则该行数据会继续走正常的哈希连接流程。
-
统计记录:
- 整个过程中,
PROBED(探测次数)和FILTERED(过滤行数)等统计信息被实时更新到内存结构中,并最终可通过V$SQL_JOIN_FILTER视图查询。
- 整个过程中,
4.3 优化器为何选择连接过滤?
优化器基于成本(Cost)决定是否使用连接过滤。它权衡的是:
- 开销:构建过滤器和为探测端每一行做检查所需的额外 CPU 时间。
- 收益:避免对大量最终不会匹配的行进行哈希计算和探测所节省的 CPU 和 I/O 时间。
当预期收益远大于开销时(即构建端小,探测端大且预计匹配行较少),优化器就会启用此功能。参数_BLOM_FILTER_ENABLED通常默认为TRUE,控制此功能的总开关。
5️⃣ 常用查询 SQL
以下是一些用于诊断和分析连接过滤器性能的实用查询。
-
查看当前库中正在使用或曾使用连接过滤器的 SQL 及其效率
SELECT s.sql_id, s.child_number, j.filter_id, s.sql_text, j.probed, j.filtered, ROUND((j.filtered / NULLIF(j.probed, 0)) * 100, 2) AS filter_efficiency_pct, j.active FROM v$sql_join_filter j JOIN v$sql s ON j.sql_id = s.sql_id AND j.child_number = s.child_number WHERE j.probed > 0 -- 确保有探测操作 ORDER BY filter_efficiency_pct DESC; -
定位特定 SQL 的执行计划中的过滤器操作
SELECT p.id, p.operation, p.options, p.object_name, p.filter_id, CASE WHEN p.operation = 'JOIN FILTER' AND p.options = 'CREATE' THEN 'Builder' WHEN p.operation = 'JOIN FILTER' AND p.options = 'USE' THEN 'User' END AS filter_role FROM v$sql_plan p WHERE p.sql_id = '&your_sql_id' -- 替换为你的SQL_ID AND p.child_number = &your_child_number AND p.operation LIKE 'JOIN FILTER%' ORDER BY p.id; -
结合执行计划,全面分析某个过滤器的性能
SELECT p.sql_id, p.child_number, p.filter_id, (SELECT object_name FROM v$sql_plan pp WHERE pp.sql_id = p.sql_id AND pp.child_number = p.child_number AND pp.operation = 'JOIN FILTER' AND pp.options = 'CREATE') AS build_table, (SELECT object_name FROM v$sql_plan pp WHERE pp.sql_id = p.sql_id AND pp.child_number = p.child_number AND pp.operation = 'JOIN FILTER' AND pp.options = 'USE') AS probe_table, p.probed, p.filtered, ROUND((p.filtered / NULLIF(p.probed, 0)) * 100, 2) AS efficiency_pct FROM v$sql_join_filter p WHERE p.sql_id = '&your_sql_id' ORDER BY p.filter_id;
6️⃣ 使用场景与总结
6.1 典型使用场景
- 数据仓库查询调优:在星型模式(Star Schema)的查询中,对巨大的事实表(Fact Table)进行连接过滤是至关重要的优化手段。通过此视图确认过滤是否生效及其效率。
- OLAP 性能分析:分析复杂的报表查询,确认连接过滤是否有效减少了中间结果集的大小,从而缩短了总体执行时间。
- 并行查询监控:在并行执行中,监控
ACTIVE和BLOCKED状态,诊断是否因过滤器构建过慢而导致并行从属进程空闲等待。 - 执行计划验证:当您看到执行计划中有
JOIN FILTER操作时,使用此视图来验证该操作在实际执行中是否真的起到了积极效果。
6.2 重要总结与最佳实践
V$SQL_JOIN_FILTER是 洞察 Bloom Filter 优化效果的“仪表盘”。FILTERED / PROBED比率是核心指标,比率越高,优化效果越好。- 连接过滤是 Oracle 优化器自动化程度非常高的一项优化技术。通常不需要手动干预(如使用 Hint
PX_JOIN_FILTER/NO_PX_JOIN_FILTER),除非在非常特殊的情况下(例如,过滤器本身开销极大且效率极低)。 - 如果发现过滤效率很低(例如低于 10%),可能意味着优化器的成本估算有误,或者连接条件的选择性不好。这可能是需要收集统计信息或调整 SQL 的信号。
- 该视图中的数据是累计的,并且会在游标被 aged out 出共享池后消失。对于长期性能分析,应依赖 AWR 历史数据(
DBA_HIST_*视图)。
通过掌握 V$SQL_JOIN_FILTER 视图,您可以深入理解 Oracle 如何智能地减少数据连接量,并能够量化地评估这一重要优化技术的实际效果,从而成为一名更深度的性能诊断专家。
欢迎关注我的公众号《IT小Chen》
783

被折叠的 条评论
为什么被折叠?



