[20260317]直接路径读决策(21c).txt
[20260317]直接路径读决策(21c).txt
--//前几天测试直接路径读遇到的情况大于_small_table_threshold的情况下全部没有数据缓存的情况下,21c全表扫描第1次采用直接路
--//径读,第2次没有有采用直接路径读,上网查了一些资料,找到链接:
https://fritshoogland.wordpress.com/2015/06/29/investigating-the-full-table-direct-path-buffered-decision/
--//作者遇到与我类似的情况,他的情况实际上第1次也是没有采用直接路径读。不过文章提供一个命令可以判断是否采用直接路径读。
--//拿该命令做一个分析诊断。
--//(nsmtio: non smart IO)
1.环境:
SYS@book> @ ver2
==============================
PORT_STRING : x86_64/Linux 2.4.xx
VERSION : 21.0.0.0.0
BANNER : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
BANNER_FULL : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
BANNER_LEGACY : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
CON_ID : 0
PL/SQL procedure successfully completed.
SYS@book> @ hidez filesystemio|^_small_table|^_very_large_object_threshold$|_direct_read_decision_statistics_driven|db_block_buffer
NUM N_HEX CON_ID NAME DESCRIPTION DEFAULT_VALUE SESSION_VALUE SYSTEM_VALUE ISSES ISSYS_MOD
----- ----- ------ ---------------------------------------- ------------------------------------------------------------ ------------- ------------- ------------ ----- ---------
431 1AF 0 filesystemio_options IO operations on filesystem files FALSE ASYNCH ASYNCH FALSE FALSE
1853 73D 0 db_block_buffers Number of database blocks cached in memory TRUE 0 0 FALSE FALSE
1854 73E 0 _db_block_buffers Number of database blocks cached in memory: hidden parameter TRUE 50908 50908 FALSE FALSE
1867 74B 0 _small_table_threshold lower threshold level of table size for direct reads TRUE 1018 1018 TRUE DEFERRED
1870 74E 0 _very_large_object_threshold upper threshold level of object size for direct reads TRUE 500 500 TRUE DEFERRED
4021 FB5 0 _direct_read_decision_statistics_driven enable direct read decision based on optimizer statistics TRUE TRUE TRUE TRUE IMMEDIATE
6 rows selected.
2.建立测试环境:
create table t (v varchar2(100)) pctused 1 pctfree 99 STORAGE(INITIAL 64m) tablespace users;
INSERT /*+ append */ INTO T SELECT RPAD(to_char(level,'0000'), 100, '*') FROM DUAL CONNECT BY LEVEL <= 1019;
commit ;
--//每条记录占一块,这样插入1019条记录,表一定大于_small_table_threshold。
--//分析表略。
SCOTT@book01p> @ tab2z ^t
Show tables matching condition "^t" (if schema is not specified then current user's tables only are shown)...
OWNER TABLE_NAME TYPE NUM_ROWS BLOCKS EMPTY AVGSPC ROWLEN TAB_LAST_ANALYZED DEGREE COMPRESS
----- ---------- ---- ------------ ------------- --------- ------ ------ ------------------- -------------------- --------
SCOTT T TAB 1019 1053 0 0 101 2026-03-16 10:02:20 1 DISABLED
3.测试:
--//测试前重启数据库,避免其他因素干扰,主要因为21c下测试全表扫描执行第1次采用直接路径读,第2次不采用直接路径读,后面不
--//管刷新数据缓存,还是共享池,问题无法再现。
SCOTT@book01p> @ desc t
Name Null? Type
----- -------- --------------
1 V VARCHAR2(100)
--//主要目的取消一些递归。
SCOTT@book01p> alter session set events 'trace[nsmtio]';
Session altered.
SCOTT@book01p> select count(*) from T;
COUNT(*)
----------
1019
SCOTT@book01p> select count(*) froM T;
COUNT(*)
----------
1019
--//注意2条语句执行sql_id不同。第2次执行M大写。
SCOTT@book01p> alter session set events 'trace[nsmtio] off';
Session altered.
SCOTT@book01p> @ ses2z 121 "physical reads direct|table scans \(direct read\)"
SID NAME VALUE
---------- ------------------------------ ----------
121 physical reads direct 1019
121 table scans (direct read) 1
--//确实,2次执行仅仅1次采用直接路径读。
--//跟踪文件内容如下:
----- Abridged Call Stack Trace -----
<Skipped 1 stack frames>
kcbism_int<-kkopqUseAffinity<-kkopqDeriveIODop<-kkecComputeAPDop<-kkoUpdateFroAnn<-kkodpModifyFros<-kkoipt<-kkoqbc<-apakkoqb<-apaqbdDescendents<-apaqbd<-apadrv<-opitca<-kksFullTypeCheck<-rpiswu2<-kksLoadChild<-kxsGetRuntimeLock<-kksfbc<-kkspsc0<-kksParseCursor
----- End of Abridged Call Stack Trace -----
Partial short call stack signature: 0x5d235e40c22320be
NSMTIO: kcbism: islarge 1 next 0 nblks 1053 type 3, bpid 65535, kcbisdbfc 0 kcbnhl 1024 kcbstt 1018 keep_nb 0 nbuf 56782 kcbnwp 1 kcbpstt 0 BCRM_ON 0 pmem_mapped 0 pmemstt 20 kcbnpbh 0 Exadata 0 bsz 8192 objd 4294967294
----- Abridged Call Stack Trace -----
<Skipped 1 stack frames>
kcbism_int<-qertbFetch<-qergsFetchSimple<-qergsFetch<-opifch2<-kpoal8<-opiodr<-ttcpip<-opitsk<-opiino<-opiodr<-opidrv<-sou2o<-opimai_real<-ssthrdmain<-main<-__libc_start_main
----- End of Abridged Call Stack Trace -----
Partial short call stack signature: 0xd9d1b371a448a626
NSMTIO: kcbism: islarge 1 next 0 nblks 1053 type 2, bpid 3, kcbisdbfc 0 kcbnhl 1024 kcbstt 1018 keep_nb 0 nbuf 56782 kcbnwp 1 kcbpstt 0 BCRM_ON 0 pmem_mapped 0 pmemstt 20 kcbnpbh 0 Exadata 0 bsz 8192 objd 201084
NSMTIO: kcbimd: nblks 1053 kcbstt 1018 kcbnbh 5678 kcbisdbfc 3 is_medium 0 objd 1
NSMTIO: kcbcmt1: scann age_diff adjts last_ts nbuf nblk has_val kcbisdbfc 0 17952 0 56782 1053 0 0 201084
NSMTIO: kcbivlo: nblks 1053 vlot 500 pnb 56782 kcbisdbfc 0 is_large 0
NSMTIO: qertbFetch:[MTT < OBJECT_SIZE < VLOT]: Checking cost to read from caches(local/remote) and checking storage reduction factors (OLTP/EHCC Comp)
NSMTIO: kcbdpc:DirectRead: tsn: 5, objd: 201084, objn: 201084
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ckpt: 1, nblks: 1053, ntcache: 0, ntdist:0, Exadata:0, bsz:8192, rule 0, threshold 104857600, rule_enabled 1\nDirect Path for pdb 3 tsn 5 objd 201084 objn 201084
Direct Path 1 ckpt 1, nblks 1053 ntcache 0 ntdist 0
Direct Path mndb 0 tdiob 0 txiob 0 tciob 5912
Direct path diomrc 128 dios 2 kcbisdbfc 0
kcbdpc: kx 1.500000 kc 2.000000 lhs 2106.000000 rhs_ckpt 52.128713 rhs_dp 52.128713 rio 0.049505 cached 0 Exadata 0 bsz 8192 offload_rule 0 threshold 104857600 rule_enabled 1
NSMTIO: Additional Info: VLOT=283910
Object# = 201084, Object_Size = 1053 blocks
SqlId = a3k62kvyuj1th, plan_hash_value = 2966233522, Partition# = 0
NSMTIO: fple: FALSE, sage: TRUE, isTableSpaceOnSage: 0, invalid table sapce number: FALSE, prmsdec: TRUE, is kernel txn table space encrypted: -1,is enc_ktid encrypted: -1, is sage enabled based on data -layer checks: -1, isQesSageEnabled: FALSE
*** 2026-03-17T09:28:01.754831+08:00 (BOOK01P(3))
----- Abridged Call Stack Trace -----
<Skipped 1 stack frames>
kcbism_int<-kkopqUseAffinity<-kkopqDeriveIODop<-kkecComputeAPDop<-kkoUpdateFroAnn<-kkodpModifyFros<-kkoipt<-kkoqbc<-apakkoqb<-apaqbdDescendents<-apaqbd<-apadrv<-opitca<-kksFullTypeCheck<-rpiswu2<-kksLoadChild<-kxsGetRuntimeLock<-kksfbc<-kkspsc0<-kksParseCursor
----- End of Abridged Call Stack Trace -----
Partial short call stack signature: 0x5d235e40c22320be
NSMTIO: kcbism: islarge 1 next 0 nblks 1053 type 3, bpid 65535, kcbisdbfc 0 kcbnhl 1024 kcbstt 1018 keep_nb 0 nbuf 56782 kcbnwp 1 kcbpstt 0 BCRM_ON 0 pmem_mapped 0 pmemstt 20 kcbnpbh 0 Exadata 0 bsz 8192 objd 4294967294
----- Abridged Call Stack Trace -----
<Skipped 1 stack frames>
kcbism_int<-qertbFetch<-qergsFetchSimple<-qergsFetch<-opifch2<-kpoal8<-opiodr<-ttcpip<-opitsk<-opiino<-opiodr<-opidrv<-sou2o<-opimai_real<-ssthrdmain<-main<-__libc_start_main
----- End of Abridged Call Stack Trace -----
Partial short call stack signature: 0xd9d1b371a448a626
NSMTIO: kcbism: islarge 1 next 0 nblks 1053 type 2, bpid 3, kcbisdbfc 0 kcbnhl 1024 kcbstt 1018 keep_nb 0 nbuf 56782 kcbnwp 1 kcbpstt 0 BCRM_ON 0 pmem_mapped 0 pmemstt 20 kcbnpbh 0 Exadata 0 bsz 8192 objd 201084
NSMTIO: kcbimd: nblks 1053 kcbstt 1018 kcbnbh 5678 kcbisdbfc 3 is_medium 0 objd 1
NSMTIO: kcbcmt1: hit age_diff adjts last_ts nbuf nblk has_val kcbisdbfc cache_it 1 17953 17952 56782 1053 1 0 1 201084
NSMTIO: qertbFetch:NoDirectRead:[- STT < OBJECT_SIZE < MTT]:Obect's size: 1053 (blocks), Threshold: MTT(5678 blocks),
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_object_statistics: enabled, Sage: enabled,
Direct Read for serial qry: enabled(:::::::auto DR::), Ascending SCN table scan: FALSE
flashback_table_scan: FALSE, Row Versions Query: FALSE
SqlId: 1ttkpqskzracb, plan_hash_value: 2966233522, Object#: 201084, Parition#: 0 DW_scan: disabled Containers: FALSE
NSMTIO: fple: FALSE, sage: TRUE, isTableSpaceOnSage: 0, invalid table sapce number: FALSE, prmsdec: TRUE, is kernel txn table space encrypted: -1,is enc_ktid encrypted: -1, is sage enabled based on data -layer checks: -1, isQesSageEnabled: FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x03000122, fn = 12, kobjd = 201084, block cnt = 1019, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x030001a2, fn = 12, kobjd = 201084, block cnt = 891, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x03000222, fn = 12, kobjd = 201084, block cnt = 763, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x030002a2, fn = 12, kobjd = 201084, block cnt = 635, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x03000322, fn = 12, kobjd = 201084, block cnt = 507, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x030003a2, fn = 12, kobjd = 201084, block cnt = 379, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x03000422, fn = 12, kobjd = 201084, block cnt = 251, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x030004a2, fn = 12, kobjd = 201084, block cnt = 123, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
--//21c下跟踪信息比11g多了许多,感觉这些变量估计就是程序里面的变量,大量的采用缩略写。
--//注意看下划线,确实第1次采用直接路径读,第2次没有采用直接路径读。
--//两处拼写错误,到现在也没有纠正,Parition,obect,看来开发不管那个团队都是如此,不管是否大牌。
--//注意看NSMTIO: qertbFetch哪行,先粘贴下来:
NSMTIO: qertbFetch:[MTT < OBJECT_SIZE < VLOT]: Checking cost to read from caches(local/remote) and checking storage reduction factors (OLTP/EHCC Comp)
NSMTIO: qertbFetch:NoDirectRead:[- STT < OBJECT_SIZE < MTT]:Obect's size: 1053 (blocks), Threshold: MTT(5678 blocks),
--//第1次执行认为在MTT < OBJECT_SIZE < VLOT之间,明显错误,第2次执行认为STT < OBJECT_SIZE < MTT,判断正确。
--//也就是第1次执行,oracle没有做非常仔细判断,仅仅认为大于_small_table_threshold就是中表,这样第1次执行选择直接路径读。
--//而第2次执行判断正确,STT < OBJECT_SIZE < MTT ,我给命名为中小表。在新的版本中后续并没有采用直接路径读。
--//当然这是我的理解,可以认为这是oracle的bug,第1次判断错误。
--//oracle 21c 根据object_Size大小分成STT,MTT,VLOT分成4段。
--//OBJECT<STT 小表
--//STT<OBJECT<MTT 中小表? 不知道如何命名。
--//MTT<OBJECT<VLOT 中表
--//OBJECT_SIZE>VLOT 大表
--//也就是相当于oracle现在的版本抬高了直接路径读的阈值到MTT。
--//而小于MTT的情况,排除第1次全表扫描以后,采用1次直接路径读,以后根本不会采用直接路径读,而且执行:
--//alter system flush buffer_cache;
--//alter system flush shared_pool;
--//也不会再次出现直接路径读,似乎一些数据字典的信息无法清除,也许里面信息清除了,可以实现直接路径读。
https://fritshoogland.wordpress.com/2015/06/29/investigating-the-full-table-direct-path-buffered-decision/
-- The tracing on 12.1.0.2 gives a hint there is a difference in consideration between a medium segment sized smaller
than MTT (medium table threshold, which is 5 times _small_table_threshold) and bigger than it. This is because of the
function kcbcmt1 showing aging/timing information on the blocks when a segment is smaller than MTT.
-- 12.1.0.2的跟踪数据表明,当数据段大小小于 MTT(中等表阈值,即small_table_threshold的5倍)或大于 MTT 时,系统会进行不同的
处理。这是因为当数据段小于 MTT 时,kcbcmt1函数会显示块的时效/定时信息。
--//顺便提一下,原始链接作者似乎遇到我类似的问题,但是我遇到遇到的情况有点不同,作者的观点如下:
https://fritshoogland.wordpress.com/2015/06/29/investigating-the-full-table-direct-path-buffered-decision/
Actually, a hint is visible in the first run. If we were to do a direct path read, how come ckpt: 0? I can not see how
it would be possible to do a direct path scan when there are changes on blocks in the cache. The answer comes from
combining the nsmtio trace with a SQL trace:
实际上,首次运行时已发现线索。若执行直接路径读取,为何会显示ckpt: 0?当缓存区块存在变更时,如何实现直接路径扫描?该问题
的答案源于将nsmtio跟踪与SQL跟踪相结合的分析。
alter session set events 'trace[nsmtio]:sql_trace level 8';
alter session set events 'trace[nsmtio] off:sql_trace off';
Here is the relevant part of the trace:
NSMTIO: qertbFetch:[MTT < OBJECT_SIZE < VLOT]: Checking cost to read from caches(local/remote) and checking storage reduction factors (OLTP/EHCC Comp)
NSMTIO: kcbdpc:DirectRead: tsn: 7, objd: 16100, objn: 16100
ckpt: 0, nblks: 52791, ntcache: 26326, ntdist:26326
NSMTIO: Additional Info: VLOT=2407385
Object# = 16100, Object_Size = 52791 blocks
SqlId = 6b258jhbcbwbh, plan_hash_value = 3364514158, Partition# = 0
*** 2015-06-29 08:48:18.825
WAIT #140240535473320: nam='cell multiblock physical read' ela= 1484 cellhash#=3176594409 diskhash#=1604910222 bytes=1015808 obj#=16100 tim=1435585698825188
WAIT #140240535473320: nam='cell multiblock physical read' ela= 1421 cellhash#=3176594409 diskhash#=1604910222 bytes=1048576 obj#=16100 tim=1435585698828291
The wait events 'cell multilbock physical read' is a buffered read. So, despite 'kcbdpc:DirectRead' from the nsmtio
trace, this is actually doing a buffered read. I am not really happy the trace is inconsistent. You could argue that it
is an Oracle internal tracing function, so Oracle can and will not guarantee anything, but this way the tracing could
tell the wrong story.
等待事件中的'cell multilbock physical read'属于缓冲读取操作。因此,尽管nsmtio跟踪显示'kcbdpc: DirectRead',实际执行的仍
是缓冲读取。我对这种跟踪数据不一致的情况感到不满。虽然有人可能认为这是Oracle的内部跟踪功能,因此Oracle无法保证其准确性,
但这种处理方式可能导致跟踪结果出现偏差。
--//作者认为实际上缓存读取,我也重复了测试,情况与他遇到的不同,结果不再贴出。
4.关于STT,MTT,VLOT的计算或者来源。
--//其中VLOT,MTT的值是最为困惑对于21c的版本。
--//STT 来源_small_table_threshold=1018,它实际上占_db_block_buffers 的2%,_db_block_buffers=50908,50908*0.02 = 1018.16
--//VLOT:
--//NSMTIO: Additional Info: VLOT=283910
--//如果按照11g的计算: _db_block_buffers*5,也就是数据缓存的5倍, 50908*5 = 254540 ,明显不对。
--//nbuf 56782 来计算 56782*5 = 283910 ,完全正确。
--//这里nbuf很容易猜测缓存数量,问题是该值来源那里呢.
--// 56782-50908 = 5874 ,相差5874.
--//MTT:
--//NSMTIO: qertbFetch:NoDirectRead:[- STT < OBJECT_SIZE < MTT]:Obect's size: 1053 (blocks), Threshold: MTT(5678 blocks),
--//这个值明显就是nbuf/10, kcbnbh 5678,相当于数据缓存的10%。非常接近 _small_table_threshold*5
--//按照https://fritshoogland.wordpress.com/2015/06/29/investigating-the-full-table-direct-path-buffered-decision/,
--//MTT等于_small_table_threshold*5=5090,估计没有pdb环境是正确的。
--//kcbnbh 表示 kernel cache buffer number of buffer headers; the size of the cache in blocks.后面的the size of the
--//cache in blocks什么意思。
--//查询x$bh,这个值存在变化。
SYS@book> select count(*) from x$bh;
COUNT(*)
----------
21564
--//使用一段时间后。
SYS@book> select count(*) from x$bh;
COUNT(*)
----------
40279
--//pdb下查询类似,总之不知道MTT,VLOT的值来源的nbuf是如何计算或者来源。
5.补充验证MTT值:
--//参考链接:[20260215]测试直接路径读的阈值(21c).txt
--//以GET_ADR_TRSH为蓝本,修改如下:
CREATE OR REPLACE FUNCTION GET_ADR_TRSH1(P_STEP IN NUMBER,
P_START IN NUMBER DEFAULT 0,
P_STOP IN NUMBER DEFAULT NULL)
RETURN NUMBER IS
L_PRD NUMBER;
L_PRD1 NUMBER;
L_PRD2 NUMBER;
L_CNT NUMBER;
L_BLOCKS NUMBER := 0;
L_START NUMBER := P_START;
BEGIN
EXECUTE IMMEDIATE 'truncate table t';
LOOP
INSERT /*+ append */
INTO T
SELECT RPAD('*', 100, '*')
FROM DUAL
CONNECT BY LEVEL <= P_STEP + L_START;
COMMIT;
L_BLOCKS := L_BLOCKS + P_STEP + L_START;
L_START := 0;
EXECUTE IMMEDIATE 'alter system flush buffer_cache';
SELECT /*+ full(t) */ COUNT(*) INTO L_CNT FROM T;
SELECT VALUE INTO L_PRD1 FROM V$SEGMENT_STATISTICS WHERE OWNER = USER AND OBJECT_NAME = 'T' AND STATISTIC_NAME = 'physical reads direct';
EXECUTE IMMEDIATE 'alter system flush buffer_cache';
SELECT /*+ full(t) */ COUNT(*) INTO L_CNT FROM T;
SELECT VALUE INTO L_PRD2 FROM V$SEGMENT_STATISTICS WHERE OWNER = USER AND OBJECT_NAME = 'T' AND STATISTIC_NAME = 'physical reads direct';
L_PRD := L_PRD2 - L_PRD1;
EXIT WHEN(L_PRD > 0 OR L_BLOCKS > NVL(P_STOP, L_BLOCKS));
END LOOP;
RETURN L_BLOCKS - P_STEP;
END;
/
$ cat m8z.txt
set serveroutput on
DECLARE
L_TRSH NUMBER;
BEGIN
L_TRSH := GET_ADR_TRSH1(10, &&1, &&2);
DBMS_OUTPUT.PUT_LINE(L_TRSH);
END;
/
SCOTT@book01p> alter session set "_optimizer_gather_stats_on_load"=false;
Session altered.
SCOTT@book01p> drop table t purge ;
Table dropped.
SCOTT@book01p> create table t (v varchar2(100)) pctused 1 pctfree 99 tablespace users;
Table created.
SCOTT@book01p> @ m8z.txt 890 8000
5570
PL/SQL procedure successfully completed.
SCOTT@book01p> exec dbms_stats.gather_table_stats('SCOTT', 'T', estimate_percent => NULL, method_opt=>'FOR TABLE FOR ALL COLUMNS SIZE REPEAT', cascade=>true, no_invalidate=>false)
PL/SQL procedure successfully completed.
SCOTT@book01p> @ tab2z ^t
Show tables matching condition "^t" (if schema is not specified then current user's tables only are shown)...
OWNER TABLE_NAME TYPE NUM_ROWS BLOCKS EMPTY AVGSPC ROWLEN TAB_LAST_ANALYZED DEGREE COMPRESS
----- ---------- ---- --------- ------- --------- ------ ------ ------------------- ----------- --------
SCOTT T TAB 5580 5678 0 0 101 2026-03-17 11:16:05 1 DISABLED
--//blocks=5678.正好等于MTT值。
SCOTT@book01p> @ ses2z 114 "physical reads direct|table scans \(direct read\)"
no rows selected
SCOTT@book01p> select count(*) from t;
COUNT(*)
----------
5580
SCOTT@book01p> @ ses2z 114 "physical reads direct|table scans \(direct read\)"
SID NAME VALUE
---------- ------------------------------ ----------
114 physical reads direct 5580
114 table scans (direct read) 1
SCOTT@book01p> select count(*) from T;
COUNT(*)
----------
5580
SCOTT@book01p> @ ses2z 114 "physical reads direct|table scans \(direct read\)"
SID NAME VALUE
---------- ------------------------------ ----------
114 physical reads direct 11160
114 table scans (direct read) 2
--//这样后续全表扫描才会选择直接路径读方式执行.
--//只有大于该数值以后,排除Block cache阀值,脏块阀值的情况下才选择直接路径读。
--//前几天测试直接路径读遇到的情况大于_small_table_threshold的情况下全部没有数据缓存的情况下,21c全表扫描第1次采用直接路
--//径读,第2次没有有采用直接路径读,上网查了一些资料,找到链接:
https://fritshoogland.wordpress.com/2015/06/29/investigating-the-full-table-direct-path-buffered-decision/
--//作者遇到与我类似的情况,他的情况实际上第1次也是没有采用直接路径读。不过文章提供一个命令可以判断是否采用直接路径读。
--//拿该命令做一个分析诊断。
--//(nsmtio: non smart IO)
1.环境:
SYS@book> @ ver2
==============================
PORT_STRING : x86_64/Linux 2.4.xx
VERSION : 21.0.0.0.0
BANNER : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
BANNER_FULL : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
BANNER_LEGACY : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
CON_ID : 0
PL/SQL procedure successfully completed.
SYS@book> @ hidez filesystemio|^_small_table|^_very_large_object_threshold$|_direct_read_decision_statistics_driven|db_block_buffer
NUM N_HEX CON_ID NAME DESCRIPTION DEFAULT_VALUE SESSION_VALUE SYSTEM_VALUE ISSES ISSYS_MOD
----- ----- ------ ---------------------------------------- ------------------------------------------------------------ ------------- ------------- ------------ ----- ---------
431 1AF 0 filesystemio_options IO operations on filesystem files FALSE ASYNCH ASYNCH FALSE FALSE
1853 73D 0 db_block_buffers Number of database blocks cached in memory TRUE 0 0 FALSE FALSE
1854 73E 0 _db_block_buffers Number of database blocks cached in memory: hidden parameter TRUE 50908 50908 FALSE FALSE
1867 74B 0 _small_table_threshold lower threshold level of table size for direct reads TRUE 1018 1018 TRUE DEFERRED
1870 74E 0 _very_large_object_threshold upper threshold level of object size for direct reads TRUE 500 500 TRUE DEFERRED
4021 FB5 0 _direct_read_decision_statistics_driven enable direct read decision based on optimizer statistics TRUE TRUE TRUE TRUE IMMEDIATE
6 rows selected.
2.建立测试环境:
create table t (v varchar2(100)) pctused 1 pctfree 99 STORAGE(INITIAL 64m) tablespace users;
INSERT /*+ append */ INTO T SELECT RPAD(to_char(level,'0000'), 100, '*') FROM DUAL CONNECT BY LEVEL <= 1019;
commit ;
--//每条记录占一块,这样插入1019条记录,表一定大于_small_table_threshold。
--//分析表略。
SCOTT@book01p> @ tab2z ^t
Show tables matching condition "^t" (if schema is not specified then current user's tables only are shown)...
OWNER TABLE_NAME TYPE NUM_ROWS BLOCKS EMPTY AVGSPC ROWLEN TAB_LAST_ANALYZED DEGREE COMPRESS
----- ---------- ---- ------------ ------------- --------- ------ ------ ------------------- -------------------- --------
SCOTT T TAB 1019 1053 0 0 101 2026-03-16 10:02:20 1 DISABLED
3.测试:
--//测试前重启数据库,避免其他因素干扰,主要因为21c下测试全表扫描执行第1次采用直接路径读,第2次不采用直接路径读,后面不
--//管刷新数据缓存,还是共享池,问题无法再现。
SCOTT@book01p> @ desc t
Name Null? Type
----- -------- --------------
1 V VARCHAR2(100)
--//主要目的取消一些递归。
SCOTT@book01p> alter session set events 'trace[nsmtio]';
Session altered.
SCOTT@book01p> select count(*) from T;
COUNT(*)
----------
1019
SCOTT@book01p> select count(*) froM T;
COUNT(*)
----------
1019
--//注意2条语句执行sql_id不同。第2次执行M大写。
SCOTT@book01p> alter session set events 'trace[nsmtio] off';
Session altered.
SCOTT@book01p> @ ses2z 121 "physical reads direct|table scans \(direct read\)"
SID NAME VALUE
---------- ------------------------------ ----------
121 physical reads direct 1019
121 table scans (direct read) 1
--//确实,2次执行仅仅1次采用直接路径读。
--//跟踪文件内容如下:
----- Abridged Call Stack Trace -----
<Skipped 1 stack frames>
kcbism_int<-kkopqUseAffinity<-kkopqDeriveIODop<-kkecComputeAPDop<-kkoUpdateFroAnn<-kkodpModifyFros<-kkoipt<-kkoqbc<-apakkoqb<-apaqbdDescendents<-apaqbd<-apadrv<-opitca<-kksFullTypeCheck<-rpiswu2<-kksLoadChild<-kxsGetRuntimeLock<-kksfbc<-kkspsc0<-kksParseCursor
----- End of Abridged Call Stack Trace -----
Partial short call stack signature: 0x5d235e40c22320be
NSMTIO: kcbism: islarge 1 next 0 nblks 1053 type 3, bpid 65535, kcbisdbfc 0 kcbnhl 1024 kcbstt 1018 keep_nb 0 nbuf 56782 kcbnwp 1 kcbpstt 0 BCRM_ON 0 pmem_mapped 0 pmemstt 20 kcbnpbh 0 Exadata 0 bsz 8192 objd 4294967294
----- Abridged Call Stack Trace -----
<Skipped 1 stack frames>
kcbism_int<-qertbFetch<-qergsFetchSimple<-qergsFetch<-opifch2<-kpoal8<-opiodr<-ttcpip<-opitsk<-opiino<-opiodr<-opidrv<-sou2o<-opimai_real<-ssthrdmain<-main<-__libc_start_main
----- End of Abridged Call Stack Trace -----
Partial short call stack signature: 0xd9d1b371a448a626
NSMTIO: kcbism: islarge 1 next 0 nblks 1053 type 2, bpid 3, kcbisdbfc 0 kcbnhl 1024 kcbstt 1018 keep_nb 0 nbuf 56782 kcbnwp 1 kcbpstt 0 BCRM_ON 0 pmem_mapped 0 pmemstt 20 kcbnpbh 0 Exadata 0 bsz 8192 objd 201084
NSMTIO: kcbimd: nblks 1053 kcbstt 1018 kcbnbh 5678 kcbisdbfc 3 is_medium 0 objd 1
NSMTIO: kcbcmt1: scann age_diff adjts last_ts nbuf nblk has_val kcbisdbfc 0 17952 0 56782 1053 0 0 201084
NSMTIO: kcbivlo: nblks 1053 vlot 500 pnb 56782 kcbisdbfc 0 is_large 0
NSMTIO: qertbFetch:[MTT < OBJECT_SIZE < VLOT]: Checking cost to read from caches(local/remote) and checking storage reduction factors (OLTP/EHCC Comp)
NSMTIO: kcbdpc:DirectRead: tsn: 5, objd: 201084, objn: 201084
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ckpt: 1, nblks: 1053, ntcache: 0, ntdist:0, Exadata:0, bsz:8192, rule 0, threshold 104857600, rule_enabled 1\nDirect Path for pdb 3 tsn 5 objd 201084 objn 201084
Direct Path 1 ckpt 1, nblks 1053 ntcache 0 ntdist 0
Direct Path mndb 0 tdiob 0 txiob 0 tciob 5912
Direct path diomrc 128 dios 2 kcbisdbfc 0
kcbdpc: kx 1.500000 kc 2.000000 lhs 2106.000000 rhs_ckpt 52.128713 rhs_dp 52.128713 rio 0.049505 cached 0 Exadata 0 bsz 8192 offload_rule 0 threshold 104857600 rule_enabled 1
NSMTIO: Additional Info: VLOT=283910
Object# = 201084, Object_Size = 1053 blocks
SqlId = a3k62kvyuj1th, plan_hash_value = 2966233522, Partition# = 0
NSMTIO: fple: FALSE, sage: TRUE, isTableSpaceOnSage: 0, invalid table sapce number: FALSE, prmsdec: TRUE, is kernel txn table space encrypted: -1,is enc_ktid encrypted: -1, is sage enabled based on data -layer checks: -1, isQesSageEnabled: FALSE
*** 2026-03-17T09:28:01.754831+08:00 (BOOK01P(3))
----- Abridged Call Stack Trace -----
<Skipped 1 stack frames>
kcbism_int<-kkopqUseAffinity<-kkopqDeriveIODop<-kkecComputeAPDop<-kkoUpdateFroAnn<-kkodpModifyFros<-kkoipt<-kkoqbc<-apakkoqb<-apaqbdDescendents<-apaqbd<-apadrv<-opitca<-kksFullTypeCheck<-rpiswu2<-kksLoadChild<-kxsGetRuntimeLock<-kksfbc<-kkspsc0<-kksParseCursor
----- End of Abridged Call Stack Trace -----
Partial short call stack signature: 0x5d235e40c22320be
NSMTIO: kcbism: islarge 1 next 0 nblks 1053 type 3, bpid 65535, kcbisdbfc 0 kcbnhl 1024 kcbstt 1018 keep_nb 0 nbuf 56782 kcbnwp 1 kcbpstt 0 BCRM_ON 0 pmem_mapped 0 pmemstt 20 kcbnpbh 0 Exadata 0 bsz 8192 objd 4294967294
----- Abridged Call Stack Trace -----
<Skipped 1 stack frames>
kcbism_int<-qertbFetch<-qergsFetchSimple<-qergsFetch<-opifch2<-kpoal8<-opiodr<-ttcpip<-opitsk<-opiino<-opiodr<-opidrv<-sou2o<-opimai_real<-ssthrdmain<-main<-__libc_start_main
----- End of Abridged Call Stack Trace -----
Partial short call stack signature: 0xd9d1b371a448a626
NSMTIO: kcbism: islarge 1 next 0 nblks 1053 type 2, bpid 3, kcbisdbfc 0 kcbnhl 1024 kcbstt 1018 keep_nb 0 nbuf 56782 kcbnwp 1 kcbpstt 0 BCRM_ON 0 pmem_mapped 0 pmemstt 20 kcbnpbh 0 Exadata 0 bsz 8192 objd 201084
NSMTIO: kcbimd: nblks 1053 kcbstt 1018 kcbnbh 5678 kcbisdbfc 3 is_medium 0 objd 1
NSMTIO: kcbcmt1: hit age_diff adjts last_ts nbuf nblk has_val kcbisdbfc cache_it 1 17953 17952 56782 1053 1 0 1 201084
NSMTIO: qertbFetch:NoDirectRead:[- STT < OBJECT_SIZE < MTT]:Obect's size: 1053 (blocks), Threshold: MTT(5678 blocks),
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_object_statistics: enabled, Sage: enabled,
Direct Read for serial qry: enabled(:::::::auto DR::), Ascending SCN table scan: FALSE
flashback_table_scan: FALSE, Row Versions Query: FALSE
SqlId: 1ttkpqskzracb, plan_hash_value: 2966233522, Object#: 201084, Parition#: 0 DW_scan: disabled Containers: FALSE
NSMTIO: fple: FALSE, sage: TRUE, isTableSpaceOnSage: 0, invalid table sapce number: FALSE, prmsdec: TRUE, is kernel txn table space encrypted: -1,is enc_ktid encrypted: -1, is sage enabled based on data -layer checks: -1, isQesSageEnabled: FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x03000122, fn = 12, kobjd = 201084, block cnt = 1019, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x030001a2, fn = 12, kobjd = 201084, block cnt = 891, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x03000222, fn = 12, kobjd = 201084, block cnt = 763, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x030002a2, fn = 12, kobjd = 201084, block cnt = 635, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x03000322, fn = 12, kobjd = 201084, block cnt = 507, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x030003a2, fn = 12, kobjd = 201084, block cnt = 379, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x03000422, fn = 12, kobjd = 201084, block cnt = 251, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
NSMTIO: kcbzib: Cache Scan triggered for tsn = 5, rdba=0x030004a2, fn = 12, kobjd = 201084, block cnt = 123, noncontig = FALSE pre-warm = FALSE, prefetch = FALSE
--//21c下跟踪信息比11g多了许多,感觉这些变量估计就是程序里面的变量,大量的采用缩略写。
--//注意看下划线,确实第1次采用直接路径读,第2次没有采用直接路径读。
--//两处拼写错误,到现在也没有纠正,Parition,obect,看来开发不管那个团队都是如此,不管是否大牌。
--//注意看NSMTIO: qertbFetch哪行,先粘贴下来:
NSMTIO: qertbFetch:[MTT < OBJECT_SIZE < VLOT]: Checking cost to read from caches(local/remote) and checking storage reduction factors (OLTP/EHCC Comp)
NSMTIO: qertbFetch:NoDirectRead:[- STT < OBJECT_SIZE < MTT]:Obect's size: 1053 (blocks), Threshold: MTT(5678 blocks),
--//第1次执行认为在MTT < OBJECT_SIZE < VLOT之间,明显错误,第2次执行认为STT < OBJECT_SIZE < MTT,判断正确。
--//也就是第1次执行,oracle没有做非常仔细判断,仅仅认为大于_small_table_threshold就是中表,这样第1次执行选择直接路径读。
--//而第2次执行判断正确,STT < OBJECT_SIZE < MTT ,我给命名为中小表。在新的版本中后续并没有采用直接路径读。
--//当然这是我的理解,可以认为这是oracle的bug,第1次判断错误。
--//oracle 21c 根据object_Size大小分成STT,MTT,VLOT分成4段。
--//OBJECT<STT 小表
--//STT<OBJECT<MTT 中小表? 不知道如何命名。
--//MTT<OBJECT<VLOT 中表
--//OBJECT_SIZE>VLOT 大表
--//也就是相当于oracle现在的版本抬高了直接路径读的阈值到MTT。
--//而小于MTT的情况,排除第1次全表扫描以后,采用1次直接路径读,以后根本不会采用直接路径读,而且执行:
--//alter system flush buffer_cache;
--//alter system flush shared_pool;
--//也不会再次出现直接路径读,似乎一些数据字典的信息无法清除,也许里面信息清除了,可以实现直接路径读。
https://fritshoogland.wordpress.com/2015/06/29/investigating-the-full-table-direct-path-buffered-decision/
-- The tracing on 12.1.0.2 gives a hint there is a difference in consideration between a medium segment sized smaller
than MTT (medium table threshold, which is 5 times _small_table_threshold) and bigger than it. This is because of the
function kcbcmt1 showing aging/timing information on the blocks when a segment is smaller than MTT.
-- 12.1.0.2的跟踪数据表明,当数据段大小小于 MTT(中等表阈值,即small_table_threshold的5倍)或大于 MTT 时,系统会进行不同的
处理。这是因为当数据段小于 MTT 时,kcbcmt1函数会显示块的时效/定时信息。
--//顺便提一下,原始链接作者似乎遇到我类似的问题,但是我遇到遇到的情况有点不同,作者的观点如下:
https://fritshoogland.wordpress.com/2015/06/29/investigating-the-full-table-direct-path-buffered-decision/
Actually, a hint is visible in the first run. If we were to do a direct path read, how come ckpt: 0? I can not see how
it would be possible to do a direct path scan when there are changes on blocks in the cache. The answer comes from
combining the nsmtio trace with a SQL trace:
实际上,首次运行时已发现线索。若执行直接路径读取,为何会显示ckpt: 0?当缓存区块存在变更时,如何实现直接路径扫描?该问题
的答案源于将nsmtio跟踪与SQL跟踪相结合的分析。
alter session set events 'trace[nsmtio]:sql_trace level 8';
alter session set events 'trace[nsmtio] off:sql_trace off';
Here is the relevant part of the trace:
NSMTIO: qertbFetch:[MTT < OBJECT_SIZE < VLOT]: Checking cost to read from caches(local/remote) and checking storage reduction factors (OLTP/EHCC Comp)
NSMTIO: kcbdpc:DirectRead: tsn: 7, objd: 16100, objn: 16100
ckpt: 0, nblks: 52791, ntcache: 26326, ntdist:26326
NSMTIO: Additional Info: VLOT=2407385
Object# = 16100, Object_Size = 52791 blocks
SqlId = 6b258jhbcbwbh, plan_hash_value = 3364514158, Partition# = 0
*** 2015-06-29 08:48:18.825
WAIT #140240535473320: nam='cell multiblock physical read' ela= 1484 cellhash#=3176594409 diskhash#=1604910222 bytes=1015808 obj#=16100 tim=1435585698825188
WAIT #140240535473320: nam='cell multiblock physical read' ela= 1421 cellhash#=3176594409 diskhash#=1604910222 bytes=1048576 obj#=16100 tim=1435585698828291
The wait events 'cell multilbock physical read' is a buffered read. So, despite 'kcbdpc:DirectRead' from the nsmtio
trace, this is actually doing a buffered read. I am not really happy the trace is inconsistent. You could argue that it
is an Oracle internal tracing function, so Oracle can and will not guarantee anything, but this way the tracing could
tell the wrong story.
等待事件中的'cell multilbock physical read'属于缓冲读取操作。因此,尽管nsmtio跟踪显示'kcbdpc: DirectRead',实际执行的仍
是缓冲读取。我对这种跟踪数据不一致的情况感到不满。虽然有人可能认为这是Oracle的内部跟踪功能,因此Oracle无法保证其准确性,
但这种处理方式可能导致跟踪结果出现偏差。
--//作者认为实际上缓存读取,我也重复了测试,情况与他遇到的不同,结果不再贴出。
4.关于STT,MTT,VLOT的计算或者来源。
--//其中VLOT,MTT的值是最为困惑对于21c的版本。
--//STT 来源_small_table_threshold=1018,它实际上占_db_block_buffers 的2%,_db_block_buffers=50908,50908*0.02 = 1018.16
--//VLOT:
--//NSMTIO: Additional Info: VLOT=283910
--//如果按照11g的计算: _db_block_buffers*5,也就是数据缓存的5倍, 50908*5 = 254540 ,明显不对。
--//nbuf 56782 来计算 56782*5 = 283910 ,完全正确。
--//这里nbuf很容易猜测缓存数量,问题是该值来源那里呢.
--// 56782-50908 = 5874 ,相差5874.
--//MTT:
--//NSMTIO: qertbFetch:NoDirectRead:[- STT < OBJECT_SIZE < MTT]:Obect's size: 1053 (blocks), Threshold: MTT(5678 blocks),
--//这个值明显就是nbuf/10, kcbnbh 5678,相当于数据缓存的10%。非常接近 _small_table_threshold*5
--//按照https://fritshoogland.wordpress.com/2015/06/29/investigating-the-full-table-direct-path-buffered-decision/,
--//MTT等于_small_table_threshold*5=5090,估计没有pdb环境是正确的。
--//kcbnbh 表示 kernel cache buffer number of buffer headers; the size of the cache in blocks.后面的the size of the
--//cache in blocks什么意思。
--//查询x$bh,这个值存在变化。
SYS@book> select count(*) from x$bh;
COUNT(*)
----------
21564
--//使用一段时间后。
SYS@book> select count(*) from x$bh;
COUNT(*)
----------
40279
--//pdb下查询类似,总之不知道MTT,VLOT的值来源的nbuf是如何计算或者来源。
5.补充验证MTT值:
--//参考链接:[20260215]测试直接路径读的阈值(21c).txt
--//以GET_ADR_TRSH为蓝本,修改如下:
CREATE OR REPLACE FUNCTION GET_ADR_TRSH1(P_STEP IN NUMBER,
P_START IN NUMBER DEFAULT 0,
P_STOP IN NUMBER DEFAULT NULL)
RETURN NUMBER IS
L_PRD NUMBER;
L_PRD1 NUMBER;
L_PRD2 NUMBER;
L_CNT NUMBER;
L_BLOCKS NUMBER := 0;
L_START NUMBER := P_START;
BEGIN
EXECUTE IMMEDIATE 'truncate table t';
LOOP
INSERT /*+ append */
INTO T
SELECT RPAD('*', 100, '*')
FROM DUAL
CONNECT BY LEVEL <= P_STEP + L_START;
COMMIT;
L_BLOCKS := L_BLOCKS + P_STEP + L_START;
L_START := 0;
EXECUTE IMMEDIATE 'alter system flush buffer_cache';
SELECT /*+ full(t) */ COUNT(*) INTO L_CNT FROM T;
SELECT VALUE INTO L_PRD1 FROM V$SEGMENT_STATISTICS WHERE OWNER = USER AND OBJECT_NAME = 'T' AND STATISTIC_NAME = 'physical reads direct';
EXECUTE IMMEDIATE 'alter system flush buffer_cache';
SELECT /*+ full(t) */ COUNT(*) INTO L_CNT FROM T;
SELECT VALUE INTO L_PRD2 FROM V$SEGMENT_STATISTICS WHERE OWNER = USER AND OBJECT_NAME = 'T' AND STATISTIC_NAME = 'physical reads direct';
L_PRD := L_PRD2 - L_PRD1;
EXIT WHEN(L_PRD > 0 OR L_BLOCKS > NVL(P_STOP, L_BLOCKS));
END LOOP;
RETURN L_BLOCKS - P_STEP;
END;
/
$ cat m8z.txt
set serveroutput on
DECLARE
L_TRSH NUMBER;
BEGIN
L_TRSH := GET_ADR_TRSH1(10, &&1, &&2);
DBMS_OUTPUT.PUT_LINE(L_TRSH);
END;
/
SCOTT@book01p> alter session set "_optimizer_gather_stats_on_load"=false;
Session altered.
SCOTT@book01p> drop table t purge ;
Table dropped.
SCOTT@book01p> create table t (v varchar2(100)) pctused 1 pctfree 99 tablespace users;
Table created.
SCOTT@book01p> @ m8z.txt 890 8000
5570
PL/SQL procedure successfully completed.
SCOTT@book01p> exec dbms_stats.gather_table_stats('SCOTT', 'T', estimate_percent => NULL, method_opt=>'FOR TABLE FOR ALL COLUMNS SIZE REPEAT', cascade=>true, no_invalidate=>false)
PL/SQL procedure successfully completed.
SCOTT@book01p> @ tab2z ^t
Show tables matching condition "^t" (if schema is not specified then current user's tables only are shown)...
OWNER TABLE_NAME TYPE NUM_ROWS BLOCKS EMPTY AVGSPC ROWLEN TAB_LAST_ANALYZED DEGREE COMPRESS
----- ---------- ---- --------- ------- --------- ------ ------ ------------------- ----------- --------
SCOTT T TAB 5580 5678 0 0 101 2026-03-17 11:16:05 1 DISABLED
--//blocks=5678.正好等于MTT值。
SCOTT@book01p> @ ses2z 114 "physical reads direct|table scans \(direct read\)"
no rows selected
SCOTT@book01p> select count(*) from t;
COUNT(*)
----------
5580
SCOTT@book01p> @ ses2z 114 "physical reads direct|table scans \(direct read\)"
SID NAME VALUE
---------- ------------------------------ ----------
114 physical reads direct 5580
114 table scans (direct read) 1
SCOTT@book01p> select count(*) from T;
COUNT(*)
----------
5580
SCOTT@book01p> @ ses2z 114 "physical reads direct|table scans \(direct read\)"
SID NAME VALUE
---------- ------------------------------ ----------
114 physical reads direct 11160
114 table scans (direct read) 2
--//这样后续全表扫描才会选择直接路径读方式执行.
--//只有大于该数值以后,排除Block cache阀值,脏块阀值的情况下才选择直接路径读。
浙公网安备 33010602011771号