专栏名称: 数据分析与开发
伯乐在线旗下账号,分享数据库相关技术文章、教程和工具,另外还包括数据库相关的工作。偶尔也谈谈程序员人生 :)
目录
相关文章推荐
数据中心运维管理  ·  2025年数据中心七大可持续性策略 ·  昨天  
数据中心运维管理  ·  数据中心规划方案 ·  17 小时前  
数据中心运维管理  ·  国内数据中心综合能耗及其灵活性预测 ·  4 天前  
数据中心运维管理  ·  超大型数据中心基础设施全生命周期维护模式的研 ... ·  4 天前  
非法加冯  ·  PostgreSQL取得对MySQL的压倒性优势 ·  3 天前  
非法加冯  ·  PostgreSQL取得对MySQL的压倒性优势 ·  3 天前  
51好读  ›  专栏  ›  数据分析与开发

为什么忘记 commit 也会造成 select 查询的性能问题

数据分析与开发  · 公众号  · 数据库  · 2017-03-28 20:38

正文

(点击 上方公众号 ,可快速关注)


作者:潇湘隐者

www.cnblogs.com/kerrycode/p/5836015.html

如有好文章投稿,请点击 → 这里了解详情


今天遇到一个很有意思的问题,一个开发人员反馈在测试服务器ORACLE数据库执行的一条简单SQL语句非常缓慢,他写的一个SQL没有返回任何数据,但是耗费了几分钟的时间。让我检查分析一下原因,分析解决过后,发现事情的真相有点让人哭笑不得,但是也是非常有意思的。我们先简单构造一下类似的案例,当然只是简单模拟。


假设一个同事A,创建了一个表并初始化了数据(实际环境数据量较大,有1G多的数据),但是他忘记提交了。我们简单模拟如下:


SQL > create table test_uncommit

2 as

3 select * from dba_objects where 1 = 0;

Table created.

SQL > declare rowIndex number;

2 begin

3 for rowIndex in 1..70 loop

4 insert into test_uncommit

5 select * from dba_objects;

6 end loop ;

7 end ;

8 /

PL / SQL procedure successfully completed.

SQL >



另外一个同事B对这个表做一些简单查询操作,但是他不知道同事A的没有提交INSERT语句,如下所示,查询时间用了大概5秒多(这个因为构造的数据量不是非常大的缘故。实际场景耗费了几分钟)


SQL > SET TIMING ON ;

SQL > SET AUTOTRACE ON ;

SQL > SELECT COUNT (1) FROM SYS.TEST_UNCOMMIT WHERE OBJECT_ID = 39;

COUNT (1)

----------

0

Elapsed: 00:00:05.38

Execution Plan

----------------------------------------------------------

Plan hash value : 970680813

------------------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 13 | 6931 (3)| 00:00:10 |

| 1 | SORT AGGREGATE | | 1 | 13 | | |

|* 2 | TABLE ACCESS FULL | TEST_UNCOMMIT | 1 | 13 | 6931 (3)| 00:00:10 |

------------------------------------------------------------------------------------

Predicate Information ( identified by operation id):

---------------------------------------------------

2 - filter( "OBJECT_ID" =39)

Note

-----

- dynamic sampling used for this statement

Statistics

----------------------------------------------------------

4 recursive calls

0 db block gets

229304 consistent gets

61611 physical reads

3806792 redo size

514 bytes sent via SQL * Net to client

492 bytes received via SQL * Net from client

2 SQL * Net roundtrips to / from client

0 sorts ( memory )

0 sorts (disk)

1 rows processed

SQL >



当时是在SQL Developer工具里面分析SQL的执行计划,并没有注意到redo size非常大的情况。刚开始怀疑是统计信息不准确导致,手工收集了一下该表的统计信息,执行的时间和执行计划依然如此,没有任何变化。 如果我们使用SQL*Plus,查看执行计划,就会看到redo size异常大,你就会有所察觉(见后面分析)


SQL > exec dbms_stats.gather_table_stats( 'SYS' , 'TEST_UNCOMMIT' );

PL / SQL procedure successfully completed.

Elapsed: 00:00:12.29


因为ORACLE里面的写不阻塞读,所以不可能是因为SQL阻塞的缘故,然后我想查看这个表到底有多少记录,结果亮瞎了我的眼睛,记录数为0,但是空间用掉了852 个数据块


SQL > SELECT TABLE_NAME, NUM_ROWS, BLOCKS FROM DBA_TABLES WHERE TABLE_NAME= 'TEST_UNCOMMIT' ;

TABLE_NAME NUM_ROWS BLOCKS

---------------------------- -- ---------- ----------

TEST_UNCOMMIT 0 852

SQL >



于是我使用Tom大师的show_space脚本检查、确认该表的空间使用情况,如下所示,该表确实使用852个数据块。


SQL > set serverout on ;

SQL > exec show_space( 'TEST_UNCOMMIT' );

Free Blocks............................. 852

Total Blocks............................ 896

Total Bytes............................. 7,340,032

Total MBytes............................ 7

Unused Blocks........................... 43

Unused Bytes............................ 352,256

Last Used Ext FileId.................... 1

Last Used Ext BlockId................... 88,201

Last Used Block......................... 85

PL / SQL procedure successfully completed.

SQL >



分析到这里,那么肯定是遇到了插入数据操作,却没有提交的缘故。用下面脚本检查发现一个会话ID为883的对这个表有一个ROW级排他锁,而且会话还有一个事务排他锁,那么可以肯定这个会话执行了DML操作,但是没有提交。


SET linesize 190

COL osuser format a15

COL username format a20 wrap

COL object_name format a20 wrap

COL terminal format a25 wrap

COL req_mode format a20

SELECT B.SID,

C.USERNAME,

C.OSUSER,

C.TERMINAL,

DECODE (B.ID2, 0, A.OBJECT_NAME,

'TRANS-'

||TO_CHAR(B.ID1)) OBJECT_NAME,

B. TYPE ,

DECODE (B.LMODE, 0, 'WAITING' ,

1, 'NULL' ,

2, 'Row-S(SS)' ,

3, 'ROW-X(SX)' ,

4, 'SHARE' ,

5, 'S/ROW-X(SSX)' ,

6, 'EXCLUSIVE'







请到「今天看啥」查看全文


推荐文章
数据中心运维管理  ·  2025年数据中心七大可持续性策略
昨天
数据中心运维管理  ·  数据中心规划方案
17 小时前
数据中心运维管理  ·  国内数据中心综合能耗及其灵活性预测
4 天前
非法加冯  ·  PostgreSQL取得对MySQL的压倒性优势
3 天前
非法加冯  ·  PostgreSQL取得对MySQL的压倒性优势
3 天前
健身课代表  ·  男生屁股很翘是种怎样的体验?
7 年前
琢磨先生  ·  你的脸就是你的运气
7 年前
宛央女子  ·  情绪不合,远比三观不合可怕
7 年前