96SEO 2026-02-20 08:11 14
[20260215]测试直接路径读的阈值(21c).txt
--//别人测试直接路径读遇到一些问题,使用如下链接还提供1个测试脚本:http://blog.itpub.net/22034023/viewspace-773483/
--//转抄如下:

11GR1
11GR2
块阀值
_small_table_threshold
统计信息里记录的表的block数目(11GR2)超过此阀值。
Block
50%
50%
少于此阀值
脏块阀值
25%
25%
少于此阀值
满足以上条件时,Oracle会进行直接路径读取。
Oracle为直接路径读取设置的三个"门槛",非常的合理:
第一个阀值:表大小,太小的表从direct
read中的获益太小。
但是特别需要引起你的警惕,如果表上存在统计信息,那么ORACLE会
采取表的统计信息中记录的block与_small_table_threshold的设定值来做比较,而不是表的真实大小(dba_segments中记录的值)。
这
可能导致一些不是你预期的情况发生。
如果你的统计信息与表的真实情况差异很大,那么你应该仔细考虑可能发生什么样的结果。
如果你
的表没有统计信息,ORACLE会依据表的真实大小来决定是否进行direct
read。
第二个阀值:脏块阀值,由于direct
read需要出发一个段的检查点,因此脏块太多,刷新脏块可能会导致IO繁忙
第三个阀值:表在内存里的cache率,如果cache率很高,那么还是走传统路径更快。
direct
read的出现,需要让ORACLE公司的开发
人员设计一个单独的结构来存储每个表有多少数据是脏数据,有多少数据被cache。
不过这个结构目前还并未暴露给我们查询。
在flush
buffer
shared_pool并不会被清空)
CREATE
NUMBER,
0,
T
'*')
DUAL
buffer_cache';
COUNT(*)
L_CNT
VALUE
L_PRD
V$SEGMENT_STATISTICS
USER
'T'
P_STEP;
END;
/
--//遇到的问题是使用该脚本在19c测试无效,重复验证测试。
1.环境:
SCOTT@book01p>
ver2
==============================
PORT_STRING
2.4.xx
VERSION
21.0.0.0.0
BANNER
Production
BANNER_FULL
21.3.0.0.0
BANNER_LEGACY
Production
CON_ID
^_small_table_threshold$
SYS@book>
pr
==============================
NUM
1867
N_HEX
74B
CON_ID
0
NAME
_small_table_threshold
DESCRIPTION
reads
DEFAULT_VALUE
TRUE
SESSION_VALUE
1018
SYSTEM_VALUE
1018
ISSES_MODIFIABLE
TRUE
ISSYS_MODIFIABLE
completed.
--//1018
2.测试环境建立:
SCOTT@book>
created.
--//实际上这样每块仅仅1条记录。
--//SCOTT@book>
sys.dbms_stats.delete_table_stats
completed.
--//建立测试函数GET_ADR_TRSH略。
SYS@book01p>
succeeded.
SYS@book01p>
DBMS_OUTPUT.PUT_LINE(L_TRSH);
END;
/
3.测试:
--//问题1:验证测试无法获取块阈值。
SCOTT@book01p>
completed.
SCOTT@book01p>
selected
--//实际上没有1次physical
direct,因为已经测试到最大值,这是遇到的第1个问题。
--//插入后并没有分析表,如果仔细阅读脚本可以发现采用直接append插入数据,第1次插入P_START+10条,后续每次在插入10条。
实际
--//上第1次插入已经存在统计信息。
SCOTT@book01p>
shown)...
OWNER
TABLE_NAME
NUM_ROWS
DEGREE
COMPRESS
--------------------
--------
SCOTT
T
TAB
905
929
0
16:09:38
1
DISABLED
--//仅仅记录了第1次执行插入的统计信息(895+10=905),以后的查询以该信息决定是否采用直接路径读,还没有到达块阈值。
--//这样即使后面继续有数据插入(每次10条),也不会采用直接路径读。
--//这是因为12c开始采用这类加载模式自动生成统计信息。
而以前测试每次执行时都是动态取样获取统计信息。
SCOTT@book01p>
dropped.
SCOTT@book01p>
created.
SCOTT@book01p>
"_optimizer_ga***r_stats_on_load"=false;
Session
altered.
--//规避统计信息加载。
SCOTT@book01p>
completed.
SCOTT@book01p>
shown)...
OWNER
TABLE_NAME
NUM_ROWS
DEGREE
COMPRESS
--------------------
--------
SCOTT
T
TAB
1
DISABLED
--//测试完成也没有统计信息。
SCOTT@book01p>
dbms_stats.ga***r_table_stats('SCOTT',
no_invalidate=>false)
PL/SQL
completed.
SCOTT@book01p>
shown)...
OWNER
TABLE_NAME
NUM_ROWS
DEGREE
COMPRESS
--------------------
--------
SCOTT
T
TAB
995
1019
0
16:21:17
1
DISABLED
--//实际上记录的985+10表示插入995条记录,如果加上段头,L1,L2的数量等于1019,应该接近1018.
--//说明该脚本测试到目前为止正确,块阀值=_small_table_threshold
4.第2个问题提出:
--//现在分析表,如果没有其他用户加载相关表T数据块,理论每次都是执行全表扫描都采用直接路径读?
--//避免其他干扰因素,重启数据库再测试。
SCOTT@book01p>
spid
==============================
SID
272
SERIAL#
2461
PROCESS
4759
SERVER
DEDICATED
SPID
4761
PID
62
P_SERIAL#
4
KILL_COMMAND
completed.
SCOTT@book01p>
selected
SCOTT@book01p>
COUNT(*)
----------
direct"
NAME
--------
direct
995
--//直接路径读,奇怪这里仅仅记录数据块执行直接路径读的次数,实际上全表扫描读取段头,可以确定该扫描那些数据块,并没有读
--//L1,L2.
SCOTT@book01p>
COUNT(*)
----------
direct"
NAME
--------
direct
995
--//可以发现没有变化,也就是第2次执行没有采用直接路径读。
SCOTT@book01p>
COUNT(*)
----------
994
--//表T数据块已经加载到数据库缓存。
SCOTT@book01p>
altered.
SCOTT@book01p>
COUNT(*)
----------
direct"
NAME
--------
direct
COUNT(*)
----------
direct"
NAME
--------
direct
995
--//刷新数据缓存后,再次执行依旧没有采用直接路径读,为什么?
5.继续分析:
SCOTT@book01p>
dbms_stats.set_table_stats('SCOTT','T',numblks=>8000,NO_INVALIDATE=>false,force=>true);
press
completed.
--//人为修改统计信息数据块数量8000。
SCOTT@book01p>
direct"
NAME
--------
direct
altered.
SCOTT@book01p>
COUNT(*)
----------
direct"
NAME
--------
direct
1990
--//再次采用直接路径读。
SCOTT@book01p>
altered.
SCOTT@book01p>
COUNT(*)
----------
direct"
NAME
--------
direct
COUNT(*)
----------
direct"
NAME
--------
direct
3980
--//修改数据块大小=8000,以后的每次执行都是直接路径读。
--//做一个猜测21c以后,不考虑Block
cache阀值,脏块阀值的情况下,oracle改变算法,大于数据块块阀值到某个值之间,第1次执行
--//全表扫描选择直接路径读,而后续的全表扫描并不采用直接路径读.如何确定这个值呢?
6.建立新的脚本:
--//以GET_ADR_TRSH为蓝本,修改如下:
CREATE
NUMBER,
0,
T
'*')
DUAL
buffer_cache';
direct';
buffer_cache';
direct';
L_PRD1;
DBMS_OUTPUT.PUT_LINE(L_TRSH);
END;
/
SCOTT@book01p>
"_optimizer_ga***r_stats_on_load"=false;
Session
altered.
SCOTT@book01p>
dropped.
SCOTT@book01p>
created.
SCOTT@book01p>
completed.
--//在测试环境测试多次,都是这个数值。
SCOTT@book01p>
shown)...
OWNER
TABLE_NAME
NUM_ROWS
DEGREE
COMPRESS
--------------------
--------
SCOTT
T
TAB
1
DISABLED
SCOTT@book01p>
dbms_stats.ga***r_table_stats('SCOTT',
no_invalidate=>false)
PL/SQL
completed.
SCOTT@book01p>
shown)...
OWNER
TABLE_NAME
NUM_ROWS
DEGREE
COMPRESS
--------------------
--------
SCOTT
T
TAB
5585
5683
0
17:17:10
1
DISABLED
--//blocks=5683.
SCOTT@book01p>
direct"
NAME
--------
direct
COUNT(*)
----------
direct"
NAME
--------
direct
29305
--//这样后续全表扫描才会选择直接路径读方式执行.
--//5683/1018
5.58251473477406679764,大于5倍,这个数值的来源于那里,实在猜测不出来。
--//还有1个疑问:
SYS@book>
COUNT(*)
----------
COUNT(*)
----------
5552
--//两者存在巨大不同,难道pdb下限制每个数据块缓存的数量吗。
SYS@book>
NAME
DESCRIPTION
------------------------------------------------------------------
74B
_small_table_threshold
reads
TRUE
1018
1018
74C
_pdb_small_table_threshold
pdb
TRUE
20
20
74D
TRUE
20
20
DEFERRED
reads
--//_pdb_small_table_threshold
表示什么,应该是百分比吗?
7.总结:
--//也许从某个版本oracle,oracle改变算法,当数据块数量在块阈值与某个数值之间,全表扫描,第1次执行采用直接路径读,后续的执
--//行并不采用直接路径读。
只有大于该数值以后,排除Block
cache阀值,脏块阀值的情况下才选择直接路径读。
--//还有1个情况,当数据块数量在块阈值与某个数值之间时,如何操作再次使执行语句采用直接路径读。
无论执行:
alter
shared_pool;
SCOTT@book01p>
shown)...
OWNER
TABLE_NAME
NUM_ROWS
DEGREE
COMPRESS
--------------------
--------
SCOTT
T
TAB
995
1019
0
15:59:08
1
DISABLED
SCOTT@book01p>
selected
SCOTT@book01p>
COUNT(*)
----------
selected
--//无法如何测试都无法再现直接路径读。
--//如果这类情况不算。
这样直接路径读的阈值提高不少,而且如何确定不是很清楚。
8.附上测试脚本:
$
conditions.
--------------------------------------------------------------------------------
--
--
Purpose:
by
--
Author:
http://www.tanelpoder.com
--
--
Usage:
<statname>
--
%
--
parse
--
redo
--
parse
--
--------------------------------------------------------------------------------
select
ses.value
from
sn
where
inst_id
,class#
,FILE#
,BLOCK#
,status
,lock_element_addr
,dirty
,temp
,ping
,stale
,direct
,new
gv$bh
=
data_object_id
dba_objects
=
(
CASE
1)
'&1'
END)
=
(
CASE
0
THEN
1))
ELSE
USER
END))
'free'
v_table
select
upper(CASE
THEN
SUBSTR('&1',INSTR('&1','.')+1)
ELSE
'&1'
END
v_table,
nvl(upper(CASE
THEN
UPPER(SUBSTR('&1',1,INSTR('&1','.')-1))
ELSE
user
set_table_stats
prompt
prompt
dbms_stats.set_table_stats('&v_owner','&v_table',&2=>&3,NO_INVALIDATE=>false,force=>true);;
prompt
pause
dbms_stats.set_table_stats('&v_owner','&v_table',&2=>&3,NO_INVALIDATE=>false,force=>true);
prompt
class="post-meta-container">
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback