[20230216]奇怪的高逻辑读3.txt --//昨天在生产系统看到一条逻辑读很高的sql语句,检查发现谓词使用了DBMS_LOB.SUBSTR函数. --//开发真奇葩,我无论如何也想不出开发为什么这些写代码,当时脑子短路了,使用trunc还好理解一点. --//我开始以为主要原因是lob类型导致fetch记录是1行1行提取,逻辑读提高,但是实测的效果要高出许多倍. --//在测试环境模拟探究看看: 1.环境: SCOTT@book> @ ver1 PORT_STRING VERSION BANNER ------------------------------ -------------- -------------------------------------------------------------------------------- x86_64/Linux 2.4.xx 11.2.0.4.0 Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production 2.建立测试例子: create table t as select * from all_objects <=100; @ gts t '' '' SCOTT@book> @ desc_proc sys dbms_lob substr INPUT OWNER PACKAGE_NAME OBJECT_NAME sample : @desc_proc sys dbms_stats gather_%_stats OWNER PACKAGE_NAME OBJECT_NAME SEQUENCE ARGUMENT_NAME DATA_TYPE IN_OUT DEFAULTED ---------- ------------ ----------- -------- ------------- --------- --------- ---------- SYS DBMS_LOB SUBSTR 1 RAW OUT N 2 LOB_LOC BLOB IN N 3 AMOUNT NUMBER IN Y 4 OFFSET NUMBER IN Y 1 VARCHAR2 OUT N 2 LOB_LOC CLOB IN N 3 AMOUNT NUMBER IN Y 4 OFFSET NUMBER IN Y 1 RAW OUT N 2 FILE_LOC BFILE IN N 3 AMOUNT NUMBER IN Y 4 OFFSET NUMBER IN Y 12 rows selected. --//dbms_lob.substr函数参数与substr不一样,第2个参数AMOUNT表示取字符串的数量,第3个参数OFFSET表示字符串的偏移量. --//注意最后一列DEFAULTED表明可以不输入第2,3参数(Y),不知道缺省怎么值.可以根据下面的执行推断offset缺省值=1. 3.测试: SCOTT@book> @ sl all alter session set statistics_level = all; Session altered. SCOTT@book> select * from t where dbms_lob.substr(object_name)='DEPT'; no rows selected --//第1次执行: Plan hash value: 1601196873 ----------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | Reads | ----------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | | 3 (100)| | 0 |00:00:00.07 | 3081 | 8 | |* 1 | TABLE ACCESS FULL| T | 1 | 1 | 75 | 3 (0)| 00:00:01 | 0 |00:00:00.07 | 3081 | 8 | ----------------------------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$1 / T@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("DBMS_LOB"."SUBSTR"(INTERNAL_FUNCTION("OBJECT_NAME"))='DEPT') --//第1次执行不稳定buffers=3081,估计存在一些递规,以后执行都是1298. --//第2次执行: Plan hash value: 1601196873 -------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | -------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | | 3 (100)| | 0 |00:00:00.02 | 1298 | |* 1 | TABLE ACCESS FULL| T | 1 | 1 | 75 | 3 (0)| 00:00:01 | 0 |00:00:00.02 | 1298 | -------------------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$1 / T@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("DBMS_LOB"."SUBSTR"(INTERNAL_FUNCTION("OBJECT_NAME"))='DEPT') select * from t where dbms_lob.substr(object_name,30,1)='DEPT'; select * from t where dbms_lob.substr(object_name,30.0,1.0)='DEPT'; Plan hash value: 1601196873 -------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | -------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | | 3 (100)| | 0 |00:00:00.02 | 1298 | |* 1 | TABLE ACCESS FULL| T | 1 | 1 | 75 | 3 (0)| 00:00:01 | 0 |00:00:00.02 | 1298 | -------------------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$1 / T@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("DBMS_LOB"."SUBSTR"(INTERNAL_FUNCTION("OBJECT_NAME"),30,1)='DEPT') --//如果执行如下: select t.*,dbms_lob.substr(object_name) from t Plan hash value: 1601196873 -------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | -------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | | 3 (100)| | 100 |00:00:00.01 | 4 | | 1 | TABLE ACCESS FULL| T | 1 | 100 | 7500 | 3 (0)| 00:00:01 | 100 |00:00:00.01 | 4 | -------------------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$1 / T@SEL$1 --//仅仅4个逻辑读. SCOTT@book> select rowid from t where rownum<=1; ROWID ------------------ AABSzYAAEAAAAijAAA SCOTT@book> @ rowid AABSzYAAEAAAAijAAA OBJECT FILE BLOCK ROW ROWID_DBA DBA TEXT ---------- ---------- ---------- ---------- -------------------- -------------------- ---------------------------------------- 339160 4 2211 0 0x10008A3 4,2211 alter system dump datafile 4 block 2211 --//记录数据块的dba地址,后面有用!! 4.开启跟踪: SCOTT@book> alter system set "_trace_pin_time"=1 scope=spfile; System altered. --//重启数据库略. SCOTT@book> select * from t where dbms_lob.substr(object_name)='DEPT'; no rows selected --//讲跟踪文件内容拷贝到20230217.txt $ awk '{print $2}' 20230217.txt | sort | uniq -c | sort -rn 1210 release 301 ktswh133: 201 ktswh102: 101 ktswh100: 100 ktswh134: 100 ktswh123: 100 ktswh111: 100 ktswh110: 100 ktswh108: 100 kdlwh01: 100 kdlwh00: 2 kdswh11: --//访问表 1 ktswh130: 1 ktswh129: 1 ktswh115: 1 ktswh114: 1 ktswh107: 1 ktswh105: 1 ktswh101: 1 ktewh26: --//访问表 $ grep 0x10008a 20230217.txt pin ktewh26: kteinpscan dba 0x10008a2:4 time 2251552903 pin kdswh11: kdst_fetch dba 0x10008a3:1 time 2251553064 pin kdswh11: kdst_fetch dba 0x10008a4:1 time 2251602100 --//扫描表对应块仅仅3次. --//问题在于ktswhNNN,取出pin release行中dba值,执行如下: $ grep "pin release" 20230217.txt | awk '{print $7}' | sort | uniq -c 605 0x404b00:4 203 0x404b01:12 302 0x404b02:11 50 0x404b03:1 50 0x404b04:1 --//605+203+302+50+50 = 1210 --//0x404b00 = set dba 1,19200 = alter system dump datafile 1 block 19200 = 4213504 --//0x404b04 = set dba 1,19204 = alter system dump datafile 1 block 19204 = 4213508 --//也就是反复访问dba = 1,19200 1,19201 1,19202 1,19203 1,19204 --//dba冒号后面的数字表示怎么不知道? SCOTT@book> @ which_obj 1 19200 SCOTT@book> @ pr ============================== OWNER : SYS SEGMENT_NAME : ARGUMENT$ PARTITION_NAME : SEGMENT_TYPE : TABLE TABLESPACE_NAME : SYSTEM EXTENT_ID : 18 FILE_ID : 1 BLOCK_ID : 19200 BYTES : 1048576 BLOCKS : 128 RELATIVE_FNO : 1 PL/SQL procedure successfully completed. --//也就是反复查询SYS.ARGUMENT$获取对应支持需要那些参数吗? SELECT distinct DBMS_ROWID.ROWID_BLOCK_NUMBER (rowid) FROM sys.argument$ a WHERE procedure$='SUBSTR' AND argument IN ('LOB_LOC', 'AMOUNT', 'OFFSET'); DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) ------------------------------------ 10247 --//块对不上!! SELECT DISTINCT OBJ#, PROCEDURE$ FROM sys.argument$ WHERE ROWID BETWEEN 'AAAADfAABAAAEsAAAA' AND 'AAAADfAABAAAEsEDDD'; OBJ# PROCEDURE$ ---- ------------- 9148 FS_GETXATTR 9148 FS_READDIR 9148 FS_RELEASEDIR 9148 FS_TRUNCATE 9148 FS_MOVE 9148 FS_OPENDIR 9148 FS_CHMOD 9148 FS_CHOWN 9148 FS_REMOVEXATTR 9148 FS_SETXATTR 9148 FS_MKDIR 9148 FS_MKNOD 9148 FS_OPEN 9148 FS_UTIME 9148 FS_WRITE 9148 FS_FSYNC 9148 FS_SYMLINK 9148 FS_DESTROY 9148 FS_RELEASE 9148 FS_STATFS 9148 FS_READ 9148 FS_FLUSH 9148 FS_FSYNCDIR 9148 FS_CREAT 9148 FS_INIT 9148 FS_LINK 9148 FS_RENAME 9148 FS_RMDIR 9148 FS_LISTXATTR 9148 FS_UNLINK 9148 FS_ACCESS 31 rows selected. --//似乎是底层的一些函数. SCOTT@book> @ sl all alter session set statistics_level = all; Session altered. SCOTT@book> select dbms_lob.substr(object_name) ,t.* from t ; SCOTT@book> @ dpc '' '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID 031na24n0u8y7, child number 1 ------------------------------------- select dbms_lob.substr(object_name) ,t.* from t Plan hash value: 1601196873 -------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | -------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | | 3 (100)| | 100 |00:00:00.01 | 4 | | 1 | TABLE ACCESS FULL| T | 1 | 100 | 7500 | 3 (0)| 00:00:01 | 100 |00:00:00.01 | 4 | -------------------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$1 / T@SEL$1 --//这样查询仅仅4个逻辑读. SCOTT@book> select * from (select dbms_lob.substr(object_name) xx,t.* from t) where xx='DEPT'; no rows selected SCOTT@book> @ dpc '' '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID 9vwbhftau3207, child number 0 ------------------------------------- select * from (select dbms_lob.substr(object_name) xx,t.* from t) where xx='DEPT' Plan hash value: 1601196873 -------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | -------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | | 3 (100)| | 0 |00:00:00.05 | 1298 | |* 1 | TABLE ACCESS FULL| T | 1 | 1 | 75 | 3 (0)| 00:00:01 | 0 |00:00:00.05 | 1298 | -------------------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$F5BB74E1 / T@SEL$2 Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("DBMS_LOB"."SUBSTR"(INTERNAL_FUNCTION("OBJECT_NAME"))='DEPT') --//放弃探究!!总之不知道开发不知道为什么这样写代码.
[20230216]奇怪的高逻辑读3.txt
来源:这里教程网
时间:2026-03-03 18:21:18
作者:
编辑推荐:
下一篇:
相关推荐
-
雷神推出 MIX PRO II 迷你主机:基于 Ultra 200H,玻璃上盖 + ARGB 灯效
2 月 9 日消息,雷神 (THUNDEROBOT) 现已宣布推出基于英
-
制造商 Musnap 推出彩色墨水屏电纸书 Ocean C:支持手写笔、第三方安卓应用
2 月 10 日消息,制造商 Musnap 现已在海外推出一款 Oce
热文推荐
- 以太网分析仪
以太网分析仪
26-03-03 - 记一次资源消耗导致RAC数据库访问异常案例
记一次资源消耗导致RAC数据库访问异常案例
26-03-03 - 自动驾驶“跌伤”,百度、小马智行“强筋壮骨”
自动驾驶“跌伤”,百度、小马智行“强筋壮骨”
26-03-03 - VIAVI唯亚威SmartClass OLA-54/-55/-55M 光功率衰减器
- VIAVI唯亚威MAP 可变光衰减器模块 (mVOA)
VIAVI唯亚威MAP 可变光衰减器模块 (mVOA)
26-03-03 - VIAVI唯亚威光纤TeraVM核心测试软件
VIAVI唯亚威光纤TeraVM核心测试软件
26-03-03 - 无锡哲讯谈食品行业如何利用SAP信息化方案实现数字化转型?
无锡哲讯谈食品行业如何利用SAP信息化方案实现数字化转型?
26-03-03 - VIAVI唯亚威StrataSync托管式云解决方案
VIAVI唯亚威StrataSync托管式云解决方案
26-03-03 - Oracle11g生成手动的快照报告报错
Oracle11g生成手动的快照报告报错
26-03-03 - 【手摸手玩转 OceanBase 53】OceanBase 为什么支持读写分离部署?
