本文围绕三种场景展开:全量计数、小范围计数、WHERE存在性判断。复用两张简单表,通过语句级Hint与一次EXISTS改写测试参数。
| 概念 | 判断方法 | 本例对应含义 |
|---|---|---|
| 相关子查询 | 是否引用外层查询块的列 | B.MAIN_ID=A.ID依赖当前客户ID |
| 非相关子查询 | 不引用外层列,可以独立求值 | 单独查询RQS_DETAIL的总COUNT,不随客户ID改变 |
| 标量子查询 | 结果作为单个值,必须单列且至多一行 | 每客户COUNT(*)可作为DETAIL_CNT |
| 平坦化/去相关 | 优化器将相关依赖转换为连接、聚合等处理形式 | 改变执行方式,不改变业务结果 |
固定数据为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);
在 DIsql 会话中开启 AUTOTRACE 跟踪与会话级 SQL 执行监控,用于获取实际执行计划与节点处理行数:
-- 开启 SQL 执行计划与资源统计跟踪
SET AUTOTRACE TRACE;
-- 开启会话级 SQL 执行节点实际行数监控
ALTER SESSION SET 'MONITOR_SQL_EXEC'=1;
本次分析的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 | 配合结果组织与投影,最终返回客户字段和计数 |
保持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 |
将全量报表缩小为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客户范围
小范围的两种方式读取了同样数量的匹配明细;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%。较直接的结构与耗时优势方向一致,但没有算子计时和重复样本,少量客户且索引有效时,保留相关计数开启参数优化可能更合适。
第一步:同一条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行。
ENABLE_RQ_TO_NONREF_SPL并非开启后一定更快,应结合具体执行计划选择。本文样本中,全量计数使用取值0,减少了重复索引访问的开销;小范围计数使用取值1,相关索引访问路径更直接。仅判断是否存在时,可以评估将COUNT改写为EXISTS,但案例说明,EXISTS也可能因参数引起的计划变化而退化。
调优时,应重点关注主表入口使用了哪些过滤条件、实际输出多少行、内层是否依赖关联变量重复处理,以及连接和聚合的执行顺序。而不是只看是否使用索引或出现SPL2。参数通过语句级Hint进行对照,并结合结果一致性、多轮耗时和逻辑读验证效果;没有稳定收益时,无需调整。
ENABLE_RQ_TO_NONREF_SPL是特定相关查询转换规则的控制参数。手册定义其为动态、会话级INI参数,默认1。
手册描述该规则将相关查询表达式转换为非相关表达式,并说明目的涉及从平坦化处理转为逐行处理。结合本次计划理解:外层关联列可被处理为var,由当前外层键驱动内层求值;关闭该规则后,仍可由其他规则选择连接、分组等方式完成原查询。
| 值 | 手册含义 |
|---|---|
| 0 | 不启用本项优化 |
| 1 | 对查询项中的相关子查询表达式优化 |
| 2 | 对查询项和WHERE中的相关子查询表达式优化 |
| 4 | 相关查询采用 spl 方式去相关性后,可以作为单表过滤条件 支持使用上述有效值的组合值,如 3 表示同时进行 1 和 2 的优化序。 |
| 条件 | 测试语句 |
|---|---|
| 全量输出、重复相关索引访问累积很高 | 以语句级Hint对照0,查看是否存在优化 |
| 外层较少、每键明细少、索引可用 | 保留直接相关路径,必要时对照1 |
| WHERE只要求有无匹配 | 比较2/0;再固定参数评估EXISTS |
ENABLE_RQ_TO_SPL单独控制SPL2相关转换。因此Hint0计划仍有SPL2不代表参数无效;应检查has_var和内部访问方式。
ENABLE_CHOOSE_BY_ESTIMATE_FLAG可根据引用单表或连接的估算行数,决定是否采用相关规则。位1针对引用单表,位4针对引用表连接;位2涉及SUBQ_EXP_CVT_FLAG。连接估算可能使用动态采样,首次执行可能变慢。
文章
阅读量
获赞
