行下面的查询,并查看trace信息(trace信息的获取方面见Oracle性能分析1)
alter system flush buffer_cache;--清理缓存
select * from t2 where id = 0
trace信息为:
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.06 18 20 0 100
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.00 0.07 18 20 0 100
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 5
Rows Row Source Operation
------- ---------------------------------------------------
100 TABLE ACCESS FULL T2 (cr=20 pr=18 pw=0 time=35975 us)
查询出100行数据,物理读取的数据块数量(disk)为18,包括一个表头数据块的读取(只有17个数据块包含数据)。执行计划使用了全表扫描。
4)执行删除数据的操作
delete from T2
5)重新获取表包含的数据块数量
select blocks from user_segments where segment_name = 'T2'
结果:24
6)获取包含数据的数据块数量
select count(distinct(dbms_rowid.rowid_block_number(rowid))) block_ct from t2
结果:0
7)执行查询并查看trace信息
alter system flush buffer_cache;--清理缓存
select * from t2 where id = 0
trace信息为:
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.00 0.21 18 20 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 0.00 0.22 18 20 0 0
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 5
Rows Row Source Operation
------- ---------------------------------------------------
0 TABLE ACCESS FULL T2 (cr=20 pr=18 pw=0 time=214806 us)
我们可以看到查询出的行数是0,但任然物理读取了18个数据块,执行计划任然使用了全扫描。
修正高水位线
我们已经了解了高水位线给全扫描带来的性能问题,下面介绍了几种降低高水位线的方法。
使用truncate操作
truncate table_name
在删除数据时尽量使用truncate操作,降低高水位线。
move操作
alter table table_name move
注意move操作需要使用额外的表空间存储,会锁住表,这样其他并发的用户在表上执行的DML语句会产生等待。move操作会影响到表上的索引,因此索引需要rebuild。
shrink操作
shrink space操作,不需要任何额外的空间,但是速度要比move慢上很多。shrink命令分为下面两种:
1)只压缩空间不调整水位线,在业务繁忙时可以执行
alter table table_name shrink space compact
compact操作通过一系列insert、delete操作,将数据尽量排列在段的前面。在这个过程中需要在表上加RX锁,即只在需要移动的行上加锁。但由于涉及到rowid的改变,因此需要enable row movement。
2)调整水位线 会产生锁,可以在业务比较少的时候执行,oracle 会记住1步骤中的操作,只调整水位线
alter table big_table shrink space
使用新表
复制要保留的数据到临时表t,drop原表,然后rename临时表t为原表。