注册
SQL优化与ENABLE_RQ_TO_NONREF_SPL参数解析
培训园地/ 文章详情 /

SQL优化与ENABLE_RQ_TO_NONREF_SPL参数解析

歪比巴卜 2026/09/09 34 0 0

SQL优化与ENABLE_RQ_TO_NONREF_SPL参数解析

概要说明

本文围绕三种场景展开:全量计数、小范围计数、WHERE存在性判断。复用两张简单表,通过语句级Hint与一次EXISTS改写测试参数。

1. 测试建表和查询语句优化问题

1.1 相关、非相关、标量子查询分别是什么

概念 判断方法 本例对应含义
相关子查询 是否引用外层查询块的列 B.MAIN_ID=A.ID依赖当前客户ID
非相关子查询 不引用外层列,可以独立求值 单独查询RQS_DETAIL的总COUNT,不随客户ID改变
标量子查询 结果作为单个值,必须单列且至多一行 每客户COUNT(*)可作为DETAIL_CNT
平坦化/去相关 优化器将相关依赖转换为连接、聚合等处理形式 改变执行方式,不改变业务结果

1.2 环境建表与测试SQL

固定数据为10万客户、90万明细;ID 1~90000每客户10条,其余1万客户无明细。

CREATE TABLE RQS_MAIN (ID INT PRIMARY KEY, NAME VARCHAR(40)); CREATE TABLE RQS_DETAIL (DETAIL_ID INT PRIMARY KEY, MAIN_ID INT NOT NULL, REMARK VARCHAR(100)); INSERT INTO RQS_MAIN SELECT LEVEL,'CUSTOMER_'||LEVEL FROM DUAL CONNECT BY LEVEL<=100000; INSERT INTO RQS_DETAIL SELECT LEVEL,MOD(LEVEL-1,90000)+1,RPAD('TEST',80,'X') FROM DUAL CONNECT BY LEVEL<=900000; COMMIT; CREATE INDEX IDX_RQS_DETAIL_ID ON RQS_DETAIL(MAIN_ID);

1.3 诊断工具开启

在 DIsql 会话中开启 AUTOTRACE 跟踪与会话级 SQL 执行监控,用于获取实际执行计划与节点处理行数:

-- 开启 SQL 执行计划与资源统计跟踪 SET AUTOTRACE TRACE; -- 开启会话级 SQL 执行节点实际行数监控 ALTER SESSION SET 'MONITOR_SQL_EXEC'=1;

1.4 初始耗时与执行计划分析

本次分析的SQL要求返回每个客户及其明细数量,先指定Hint1作为基线:

SELECT /*+ ENABLE_RQ_TO_NONREF_SPL(1) PLAN_NO_CACHE*/ A.ID,A.NAME, (SELECT COUNT(*) FROM RQS_DETAIL B WHERE B.MAIN_ID=A.ID) AS DETAIL_CNT FROM RQS_MAIN A;
1 #NSET2: [11, 100000->100000, 64] 2 #PIPE2: [11, 100000->100000, 64] 3 #PRJT2: [11, 100000->100000, 64]; exp_num(4), is_atom(FALSE); INFO_BITS(0) 4 #CSCN2: [11, 100000->100000, 64]; INDEX33555506(RQS_MAIN); btr_scan(1); need_slct(0) prejudge_iescn(0) 5 #SPL2: [1, 1->0, 4]; key_num(1), spool_num(0), is_atom(1), has_var(1), sites(-), result_cache(FALSE) 6 #PRJT2: [1, 1->100000, 4]; exp_num(1), is_atom(TRUE); INFO_BITS(0) 7 #AAGR2: [1, 1->100000, 4]; grp_num(0), sfun_num(1), distinct_flag[0]; slave_empty(0) 8 #SSEK2: [1, 1->900000, 4]; scan_type(ASC), IDX_RQS_DETAIL_ID(RQS_DETAIL), is_global(0), scan_range[var1,var1] Statistics ----------------------------------------------------------------- 0 data pages changed 0 undo pages changed 303347 logical reads 0 physical reads 0 direct physical reads 0 redo size 5189767 bytes sent to client 861 bytes received from client 11 roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 0 rows processed 0.000 io wait time(ms) 574.867 exec time(ms)

先看第4行CSCN2,这是主表RQS_MAIN的入口,估算和实际输出都是100000行。SQL没有限制客户范围,因此后续需要为10万个客户分别得到明细数量,接着看第5行SPL2,其中has_var(1)说明这个分支保留变量依赖。再看第8行SSEK2,使用的是IDX_RQS_DETAIL_ID索引,范围为SCAN_RANGE[var1,var1]。这里的var1来自外层A.ID,也就是把当前客户编号交给内层,查找属于该客户的明细。可以按类似嵌套循环的“外层提供键、内层按键求值”理解,最后看第7行AAGR2,grp_num(0)对应没有GROUP BY的计数,累计输出100000行;第8行累计输出900000条明细,与9万个客户各10条、1万个客户无明细的分布一致。

计划行号 算子/字段 在本SQL中的作用
4 CSCN2,RQS_MAIN→100000 主表全扫描,为后续计算提供客户ID及NAME
5 SPL2,has_var(1) 该分支保留外层变量依赖,不是独立的一次全表计数
8 SSEK2,[var1,var1]→900000 按当前客户ID定位明细索引,累计输出90万条明细
7 AAGR2,grp_num(0)→100000 对各次相关求值的匹配行计数,无明细客户也得到0
1~3、6 NSET2、PIPE2、PRJT2 配合结果组织与投影,最终返回客户字段和计数

2. 三个场景的优化实战

2.1 场景一:全量计数的Hint对照

保持SQL、数据、索引和统计信息不变,仅将Hint值改为0, 0表示不启用该项相关查询优化:

SELECT /*+ ENABLE_RQ_TO_NONREF_SPL(0) */ A.ID,A.NAME, (SELECT COUNT(*) FROM RQS_DETAIL B WHERE B.MAIN_ID=A.ID) AS DETAIL_CNT FROM RQS_MAIN A;
1 #NSET2: [202, 100000->100000, 64] 2 #PIPE2: [202, 100000->100000, 64] 3 #PRJT2: [11, 100000->100000, 64]; exp_num(4), is_atom(FALSE); INFO_BITS(0) 4 #CSCN2: [11, 100000->100000, 64]; INDEX33555506(RQS_MAIN); btr_scan(1); need_slct(0) prejudge_iescn(0) 5 #SPL2: [190, 100000->0, 64]; key_num(2), spool_num(0), is_atom(0), has_var(0), sites(-), result_cache(FALSE) 6 #PRJT2: [190, 100000->100000, 64]; exp_num(3), is_atom(FALSE); INFO_BITS(0) 7 #HAGR2: [190, 100000->100000, 64]; grp_num(1), sfun_num(2), MEM_USED(3995KB), DISK_USED(0KB), distinct_flag[0,0]; slave_empty(0) keys(A.ROWID) 8 #HASH LEFT JOIN2: [183, 100000->910000, 64]; key_num(1); col_num(2); partition_keys_num(0); mix(0); MEM_USED(23300KB), DISK_USED(0KB) KEY(A.ID=B.MAIN_ID) 9 #CSCN2: [11, 100000->100000, 64]; INDEX33555506(RQS_MAIN); btr_scan(1); need_slct(0) prejudge_iescn(0) 10 #SSCN: [97, 900000->900000, 16]; IDX_RQS_DETAIL_ID(RQS_DETAIL); btr_scan(1); is_global(0) Statistics ----------------------------------------------------------------- 0 data pages changed 0 undo pages changed 3418 logical reads 0 physical reads 0 direct physical reads 0 redo size 5189767 bytes sent to client 861 bytes received from client 11 roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 0 rows processed 0.000 io wait time(ms) 165.115 exec time(ms)

仍先看第4行,外层主表实际输出100000行,说明业务范围没有变化。然后看第5行SPL2:has_var从1变成0、is_atom从1变成0,内部已不是原来按var1定位并计数的结构。继续沿SPL2的子树看:第9行CSCN2读取10万客户,第10行SSCN扫描明细索引、实际输出90万行;第8行HASH LEFT JOIN2按A.ID=B.MAIN_ID连接,输出910000行;第7行HAGR2再按A.ROWID聚合,得到100000行。主表在第4行和第9行各出现一次。这个计划并不是所有步骤都减少,而是改变了主要访问方式:明细由大量按键定位变成索引扫描和批量连接。最终逻辑读降到3418,说明这里增加的连接、分组工作,比原来的重复访问方式更划算。

原计划行号 算子/字段 数据如何变化
4 外层CSCN2→100000 仍保留外层主表访问分支
9、10 内部CSCN2、SSCN 连接分支再次读取主表10万行,并扫描明细索引90万行
8 HASH LEFT JOIN2→910000 匹配明细展开,同时保留无匹配客户
7 HAGR2,keys(A.ROWID)→100000 按主表每一行聚合,恢复每客户一个计数结果
5 SPL2,has_var(0) 该分支不再以原来的外层var逐键计数形式工作
阶段 Hint 逻辑读 exec time(ms) 实际输出行数
基线 1 303347 574.867 100000
对照 0 3418 165.115 100000

2.2 场景二:小范围查询

将全量报表缩小为500个客户,分别执行:

SELECT /*+ ENABLE_RQ_TO_NONREF_SPL(0) */ A.ID,A.NAME, (SELECT COUNT(*) FROM RQS_DETAIL B WHERE B.MAIN_ID=A.ID) AS DETAIL_CNT FROM RQS_MAIN A WHERE A.ID<=500; SELECT /*+ ENABLE_RQ_TO_NONREF_SPL(1) */ A.ID,A.NAME, (SELECT COUNT(*) FROM RQS_DETAIL B WHERE B.MAIN_ID=A.ID) AS DETAIL_CNT FROM RQS_MAIN A WHERE A.ID<=500;
ENABLE_RQ_TO_NONREF_SPL(0): 1 #NSET2: [4, 479->500, 64] 2 #PIPE2: [4, 479->500, 64] 3 #PRJT2: [1, 479->500, 64]; exp_num(4), is_atom(FALSE); INFO_BITS(0) 4 #BLKUP2: [1, 479->500, 64]; INDEX33555507(RQS_MAIN); use_clu_addr(0) 5 #SSEK2: [1, 479->500, 64]; scan_type(ASC), INDEX33555507(RQS_MAIN), is_global(0), scan_range(null2,500] 6 #SPL2: [3, 479->0, 64]; key_num(2), spool_num(0), is_atom(0), has_var(0), sites(-), result_cache(FALSE) 7 #PRJT2: [3, 479->500, 64]; exp_num(3), is_atom(FALSE); INFO_BITS(0) 8 #HAGR2: [3, 479->500, 64]; grp_num(1), sfun_num(2), MEM_USED(1662KB), DISK_USED(0KB), distinct_flag[0,0]; slave_empty(0) keys(A.ROWID) 9 #HASH LEFT JOIN2: [2, 959->0, 64]; key_num(1); col_num(2); partition_keys_num(0); mix(0); MEM_USED(0KB), DISK_USED(0KB) KEY(A.ID=B.MAIN_ID) 10 #INDEX JOIN LEFT JOIN2: [2, 959->5000, 64]: col_num(2) ret_null(0) 11 #ACTRL: [2, 959->500, 64]; 12 #SSEK2: [1, 479->500, 64]; scan_type(ASC), INDEX33555507(RQS_MAIN), is_global(0), scan_range(null2,500] 13 #SSEK2: [2, 2->5000, 4]; scan_type(ASC), IDX_RQS_DETAIL_ID(RQS_DETAIL), is_global(0), scan_range[A.ID,A.ID] 14 #SSCN: [97, 900000, 16]; IDX_RQS_DETAIL_ID(RQS_DETAIL); btr_scan(1); is_global(0) Statistics ----------------------------------------------------------------- 0 data pages changed 0 undo pages changed 3073 logical reads 0 physical reads 0 direct physical reads 0 redo size 25188 bytes sent to client 301 bytes received from client 2 roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 0 rows processed 0.000 io wait time(ms) 15.741 exec time(ms) ENABLE_RQ_TO_NONREF_SPL(1): 1 #NSET2: [1, 479->500, 64] 2 #PIPE2: [1, 479->500, 64] 3 #PRJT2: [1, 479->500, 64]; exp_num(4), is_atom(FALSE); INFO_BITS(0) 4 #BLKUP2: [1, 479->500, 64]; INDEX33555507(RQS_MAIN); use_clu_addr(0) 5 #SSEK2: [1, 479->500, 64]; scan_type(ASC), INDEX33555507(RQS_MAIN), is_global(0), scan_range(null2,500] 6 #SPL2: [1, 1->0, 4]; key_num(1), spool_num(0), is_atom(1), has_var(1), sites(-), result_cache(FALSE) 7 #PRJT2: [1, 1->500, 4]; exp_num(1), is_atom(TRUE); INFO_BITS(0) 8 #AAGR2: [1, 1->500, 4]; grp_num(0), sfun_num(1), distinct_flag[0]; slave_empty(0) 9 #SSEK2: [1, 1->5000, 4]; scan_type(ASC), IDX_RQS_DETAIL_ID(RQS_DETAIL), is_global(0), scan_range[var1,var1] Statistics ----------------------------------------------------------------- 0 data pages changed 0 undo pages changed 3018 logical reads 0 physical reads 0 direct physical reads 0 redo size 25188 bytes sent to client 301 bytes received from client 2 roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 0 rows processed 0.000 io wait time(ms) 3.050 exec time(ms)

逐层对比:500客户范围

  • 两个计划都先用主表SSEK2限定ID≤500,再由BLKUP2获取客户行。这个回表属于主表分支,不应误写成明细REMARK回表。
  • Hint1第9行按[var1,var1]读取5000条明细,第8行AAGR2累计形成500个计数。
  • Hint0第10~13行显示索引连接路径:主表索引提供500个客户,明细索引按[A.ID,A.ID]匹配,连接累计输出5000行;第8行HAGR2再聚合成500行。
  • Hint0第9行Hash节点显示→0,第14行SSCN没有实际输出箭头,而索引连接分支已有5000行实测输出。因此不能把计划图中所有候选节点都当作已经完成的全量工作。ACTRL提示存在执行控制,具体切换条件不能仅从这张输出还原。

小范围的两种方式读取了同样数量的匹配明细;Hint1省去了该Hint0计划中的额外连接、分组结构,

方案 实际客户数 实际明细累计输出 logical reads exec time(ms)
Hint0 500 5000 3073 15.741
Hint1 500 5000 3018 3.050

结论:本次从0改为1减少12.691 ms,耗时下降80.62%,逻辑读却只下降1.79%。较直接的结构与耗时优势方向一致,但没有算子计时和重复样本,少量客户且索引有效时,保留相关计数开启参数优化可能更合适。

2.3 场景三:WHERE判断存在

第一步:同一条COUNT查询,比较Hint2与Hint0。

SELECT /*+ ENABLE_RQ_TO_NONREF_SPL(2) */ A.ID,A.NAME FROM RQS_MAIN A WHERE (SELECT COUNT(*) FROM RQS_DETAIL B WHERE B.MAIN_ID=A.ID)>0; SELECT /*+ ENABLE_RQ_TO_NONREF_SPL(0) */ A.ID,A.NAME FROM RQS_MAIN A WHERE (SELECT COUNT(*) FROM RQS_DETAIL B WHERE B.MAIN_ID=A.ID)>0;
ENABLE_RQ_TO_NONREF_SPL(2): 1 #NSET2: [12, 5000->90000, 64] 2 #PIPE2: [12, 5000->90000, 64] 3 #PRJT2: [12, 5000->90000, 64]; exp_num(3), is_atom(FALSE); INFO_BITS(0) 4 #SLCT2: [12, 5000->90000, 64]; exp67 > var2, slct_pushdown(0) 5 #CSCN2: [12, 100000->100000, 64]; INDEX33555506(RQS_MAIN); btr_scan(1); need_slct(0) prejudge_iescn(0) 6 #SPL2: [1, 1->0, 4]; key_num(1), spool_num(0), is_atom(1), has_var(1), sites(-), result_cache(FALSE) 7 #PRJT2: [1, 1->100000, 4]; exp_num(1), is_atom(TRUE); INFO_BITS(0) 8 #AAGR2: [1, 1->100000, 4]; grp_num(0), sfun_num(1), distinct_flag[0]; slave_empty(0) 9 #SSEK2: [1, 1->900000, 4]; scan_type(ASC), IDX_RQS_DETAIL_ID(RQS_DETAIL), is_global(0), scan_range[var1,var1] Statistics ----------------------------------------------------------------- 0 data pages changed 0 undo pages changed 303389 logical reads 0 physical reads 0 direct physical reads 0 redo size 3589524 bytes sent to client 654 bytes received from client 8 roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 0 rows processed 0.000 io wait time(ms) 476.571 exec time(ms) ENABLE_RQ_TO_NONREF_SPL(0): 1 #NSET2: [267, 45000->90000, 68] 2 #PRJT2: [267, 45000->90000, 68]; exp_num(3), is_atom(FALSE); INFO_BITS(0) 3 #SLCT2: [267, 45000->90000, 68]; exp11 > var1, slct_pushdown(0) 4 #HASH LEFT JOIN2: [237, 900000->100000, 68]; key_num(1); col_num(5); partition_keys_num(0); mix(0); MEM_USED(24324KB), DISK_USED(0KB) KEY(A.ID=DMTEMPVIEW_889197337.colname) 5 #CSCN2: [11, 100000->100000, 64]; INDEX33555506(RQS_MAIN); btr_scan(1); need_slct(0) prejudge_iescn(0) 6 #PRJT2: [153, 900000->90000, 4]; exp_num(3), is_atom(FALSE); INFO_BITS(0) 7 #SAGR2: [153, 900000->90000, 4]; grp_num(1), sfun_num(1), opt_num(0), distinct_flag[0]; slave_empty(0) keys(B.MAIN_ID) 8 #SSCN: [95, 900000->900000, 4]; IDX_RQS_DETAIL_ID(RQS_DETAIL); btr_scan(1); is_global(0) Statistics ----------------------------------------------------------------- 0 data pages changed 0 undo pages changed 2928 logical reads 0 physical reads 0 direct physical reads 0 redo size 3589524 bytes sent to client 654 bytes received from client 8 roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 0 rows processed 0.000 io wait time(ms) 62.337 exec time(ms)

先看COUNT的Hint2计划 第5行CSCN2实际输出100000行,而第4行SLCT2才输出90000行。再沿第6行SPL2往下看,第9行仍是[var1,var1]索引定位,累计输出90万条明细。这里相当于为客户取得计数,再判断是否大于0,仍承担逐客户相关处理的累计开销,因此产生303389次逻辑读。Hint2覆盖查询项和WHERE相关子查询,只是使这类转换可用,不保证它比其他策略更快。

然后看COUNT的Hint0计划 第8行SSCN先读90万条明细,第7行SAGR2以B.MAIN_ID为分组键,实际输出90000组;第4行HASH LEFT JOIN2把这9万组与第5行的10万客户关联,实际输出100000行;第3行SLCT2再过滤出90000个有明细的客户。

因此,本WHERE计划是先聚合明细再连接。这里逻辑读降至2928,耗时为62.337 ms,是当前样本中更合适的COUNT路径。

第二步:固定Hint0,将COUNT改为EXISTS。

SELECT A.ID,A.NAME FROM RQS_MAIN A WHERE EXISTS ( SELECT 1 FROM RQS_DETAIL B WHERE B.MAIN_ID=A.ID );
1 #NSET2: [179, 96770->90000, 64] 2 #PRJT2: [179, 96770->90000, 64]; exp_num(3), is_atom(FALSE); INFO_BITS(0) 3 #HASH LEFT SEMI JOIN2: [179, 96770->90000, 64]; KEY_NUM(1); MEM_USED(24255KB), DISK_USED(0KB) KEY(A.ID=B.MAIN_ID) KEY_NULL_EQU(0) 4 #CSCN2: [11, 100000->100000, 64]; INDEX33555506(RQS_MAIN); btr_scan(1); need_slct(0) prejudge_iescn(0) 5 #SSCN: [95, 900000->900000, 4]; IDX_RQS_DETAIL_ID(RQS_DETAIL); btr_scan(1); is_global(0) Statistics ----------------------------------------------------------------- 0 data pages changed 0 undo pages changed 2882 logical reads 0 physical reads 0 direct physical reads 0 redo size 3589524 bytes sent to client 651 bytes received from client 8 roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 0 rows processed 0.000 io wait time(ms) 30.958 exec time(ms)

第3行HASH LEFT SEMI JOIN2是核心。第4行仍读取10万客户,第5行仍扫描90万条明细,但原COUNT0计划中的SAGR2计数聚合和单独的计数过滤已经不在这个结构中。半连接只需要确认左侧客户是否有匹配,不需要把明细总数作为结果,因此最终输出90000个客户。

这个场景中从业务端改写sql的效果显然比使用参数要好一些。

方案 Hint 实际输出行数 主要访问结构 logical reads exec time(ms)
WHERE COUNT(*)>0 2 90000 相关索引计数后过滤 303389 476.571
WHERE COUNT(*)>0 0 90000 按MAIN_ID聚合后Hash左连接、过滤 2928 62.337
WHERE EXISTS 0 90000 Hash左半连接 2882 30.958

三个WHERE方案

方案 数据处理链 关键判断
COUNT Hint2 主表CSCN2:100000 → 相关SPL2/AAGR2:100000个计数 → SLCT2:90000 过滤前先获得每客户计数;内层仍是[var1,var1]定位
COUNT Hint0 明细SSCN:900000 → SAGR2:90000组 → Hash左连接:100000 → SLCT2:90000 先按B.MAIN_ID计数,再匹配客户并过滤无明细客户
EXISTS Hint0 主表100000+明细索引900000 → Hash左半连接:90000 按存在性保留左侧客户,不再生成每客户的计数结果

参数影响:COUNT2与COUNT0。 Hint2先扫描10万客户,相关聚合累计输出10万个计数,内层索引累计处理90万条明细,最后过滤为9万客户。Hint0先将90万明细经SAGR2按MAIN_ID聚合为9万组,再与10万客户左连接、过滤为9万行。逻辑读和耗时下降比较多,可以使用参数进行优化。

改写影响:COUNT0与EXISTS0。 固定Hint0后,EXISTS实际采用HASH LEFT SEMI JOIN2,去掉计数聚合,只按是否存在匹配筛选客户。半连接不会因一个客户有多条明细而重复返回该客户,因此输出9万行。

EXISTS相对COUNT0耗时下降50.34%。取消计数聚合是可观察的结构变化,但不能仅靠这46次逻辑读解释全部时间降幅,仍须重复采样。也不能声称“EXISTS每个客户只读一条”:本次明细SSCN明确累计输出900000行。

2.4 结论

ENABLE_RQ_TO_NONREF_SPL并非开启后一定更快,应结合具体执行计划选择。本文样本中,全量计数使用取值0,减少了重复索引访问的开销;小范围计数使用取值1,相关索引访问路径更直接。仅判断是否存在时,可以评估将COUNT改写为EXISTS,但案例说明,EXISTS也可能因参数引起的计划变化而退化。

调优时,应重点关注主表入口使用了哪些过滤条件、实际输出多少行、内层是否依赖关联变量重复处理,以及连接和聚合的执行顺序。而不是只看是否使用索引或出现SPL2。参数通过语句级Hint进行对照,并结合结果一致性、多轮耗时和逻辑读验证效果;没有稳定收益时,无需调整。

3. 关于ENABLE_RQ_TO_NONREF_SPL

3.1 参数的具体含义与作用

ENABLE_RQ_TO_NONREF_SPL特定相关查询转换规则的控制参数。手册定义其为动态、会话级INI参数,默认1。

手册描述该规则将相关查询表达式转换为非相关表达式,并说明目的涉及从平坦化处理转为逐行处理。结合本次计划理解:外层关联列可被处理为var,由当前外层键驱动内层求值;关闭该规则后,仍可由其他规则选择连接、分组等方式完成原查询。

手册含义
0 不启用本项优化
1 对查询项中的相关子查询表达式优化
2 对查询项和WHERE中的相关子查询表达式优化
4 相关查询采用 spl 方式去相关性后,可以作为单表过滤条件 支持使用上述有效值的组合值,如 3 表示同时进行 1 和 2 的优化序。

3.2 什么时候调整,什么时候不需要调整

条件 测试语句
全量输出、重复相关索引访问累积很高 以语句级Hint对照0,查看是否存在优化
外层较少、每键明细少、索引可用 保留直接相关路径,必要时对照1
WHERE只要求有无匹配 比较2/0;再固定参数评估EXISTS

3.3 相关参数

ENABLE_RQ_TO_SPL单独控制SPL2相关转换。因此Hint0计划仍有SPL2不代表参数无效;应检查has_var和内部访问方式。

ENABLE_CHOOSE_BY_ESTIMATE_FLAG可根据引用单表或连接的估算行数,决定是否采用相关规则。位1针对引用单表,位4针对引用表连接;位2涉及SUBQ_EXP_CVT_FLAG。连接估算可能使用动态采样,首次执行可能变慢。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服