ITPub博客

首页 > 数据库 > Oracle > 手动降低高水位线

手动降低高水位线

原创 Oracle 作者:skyin_1603 时间:2016-10-16 00:09:11 0 删除 编辑
一张表,当用delete删除时,数据是被删除了,可是在数据块中的空间还没有释放,则高水位线
依然在原来的位置,当我们查询该表的数据时候,空块依然还被搜索。为了提高查询效率,降低I/O
的读取,我们不得不进行人为手动降低高水位线。

操作如下:
1、创建表与索引:
SQL> create table emp tablespace users as select * from hr.employees where 1=0;

Table created.

SQL> create index idx_emp_salary on emp(salary) tablespace users;

Index created.

2、往表里插入数据:
SQL> begin
  2       for i in 1..500 loop
  3         insert into emp select * from hr.employees;
  4        end loop;
  5        commit;
  6       end;
  7  /
PL/SQL procedure successfully completed.

3、查询数据:
SQL> select count(*) from emp;

  COUNT(*)
----------
     53500

4、查看表的索引状态:
SQL> select INDEX_NAME,STATUS from user_indexes where INDEX_NAME=upper('idx_emp_salary');

INDEX_NAME                     STATUS
------------------------------ --------
IDX_EMP_SALARY                 VALID

5、查看表的系统信息:
SQL> SELECT num_rows, blocks, empty_blocks as empty, avg_space, chain_cnt, avg_row_len
  2         FROM user_tables where table_name = 'EMP';

  NUM_ROWS     BLOCKS      EMPTY  AVG_SPACE  CHAIN_CNT AVG_ROW_LEN
---------- ---------- ---------- ---------- ---------- -----------


6、收集emp的统计信息:
SQL> exec dbms_stats.gather_table_stats(user,'EMP')

PL/SQL procedure successfully completed.

7、再次查看表的系统信息:
SQL> SELECT num_rows, blocks, empty_blocks as empty, avg_space, chain_cnt, avg_row_len
  2         FROM user_tables where table_name = 'EMP';

  NUM_ROWS     BLOCKS      EMPTY  AVG_SPACE  CHAIN_CNT AVG_ROW_LEN
---------- ---------- ---------- ---------- ---------- -----------
     53500        622          0          0          0          69
 
现在看,表中一共有53500条数据,则有53500个rowid,622个快.  


8、查看查询执行计划的统计信息:   
     SQL> set autot trace stat
SQL> select count(*) from emp;

Statistics
----------------------------------------------------------
         18  recursive calls
          0  db block gets
        585  consistent gets
          0  physical reads
          0  redo size
        527  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          4  sorts (memory)
          0  sorts (disk)
          1  rows processed
现在的该查询语句的 I/O 读取数为585。  
          
9、删除50000条数据再查询:
 SQL> set autot off
SQL> delete emp where rownum<=50000;

50000 rows deleted.

SQL> commit;
Commit complete.

10、再次收集emp表的统计信息:
SQL> exec dbms_stats.gather_table_stats(user,'EMP')

PL/SQL procedure successfully completed.


11、再次查询表的系统信息,看到表的数据减少到3500:
SQL> SELECT num_rows, blocks, empty_blocks as empty, avg_space, chain_cnt, avg_row_len
  2      FROM user_tables where table_name = 'EMP';

  NUM_ROWS     BLOCKS      EMPTY  AVG_SPACE  CHAIN_CNT AVG_ROW_LEN
---------- ---------- ---------- ---------- ---------- -----------
      3500        622          0          0          0          69
可以看到,删除了50000条数据后,数据的是少了,可是段中的数据库没有少,依然是622个快,
很明显其中包括了大量的空块。

12、再次收集查询执行计划的统计信息:
SQL> set autotrace trace stat
SQL> select count(*) from emp;

Statistics
----------------------------------------------------------
         18  recursive calls
          0  db block gets
        585  consistent gets
          0  physical reads
          0  redo size
        526  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          4  sorts (memory)
          0  sorts (disk)
          1  rows processed
该查询语句的 I/O 读取数依然为585,可为什么还这么多呢?不是已经删除了的大部分的数据了吗?
                  
13、进行一次行移动:
 SQL> set autotrace off
SQL> alter table emp enable row movement;

Table altered.

14、在进行收缩空间:
收缩空快的空间:
SQL> alter table emp shrink space;

Table altered.
这个动作就是回收空块的空间,降低高水位线。

15、收缩后,查看查询的读取统计信息:
SQL> select count(*) from emp;

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
         38  consistent gets
          8  physical reads
          0  redo size
        526  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
 这时候,才有效地降低了 I/O 读取数。      
    
16、查看emp索引的状态:  
set autot off        
 SQL> select INDEX_NAME,STATUS from user_indexes where INDEX_NAME=upper('idx_emp_salary');

INDEX_NAME                     STATUS
------------------------------ --------
IDX_EMP_SALARY                 VALID

17、关闭行移动功能:
SQL> alter table emp disable row movement;

Table altered.

18、再次查看行移动功能的状态:
SQL> select table_name,ROW_MOVEMENT from user_tables where table_name='EMP';

TABLE_NAME                     ROW_MOVE
------------------------------ --------
EMP                            DISABLED
已关闭。

很明显,当高水位降低后,逻辑读已经大大减少了。此时的性能一定会好于之前。

19、测试行移动或表移动对索引的影响:
SQL> alter table emp move; 

Table altered.
表移动.

20、查看表emp索引的状态:
SQL> select INDEX_NAME,STATUS from user_indexes where INDEX_NAME=upper('idx_emp_salary');

INDEX_NAME                     STATUS
------------------------------ --------
IDX_EMP_SALARY                 UNUSABLE


表移动后,查看索引状态,发现索引以失效。


21、重建索引:
SQL> alter index IDX_EMP_SALARY rebuild;

Index altered.

22、重建索引后,查看索引的状态:
SQL> select INDEX_NAME,STATUS from user_indexes where INDEX_NAME=upper('idx_emp_salary');

INDEX_NAME                     STATUS
------------------------------ --------
IDX_EMP_SALARY                 VALID

表索引已经恢复原来的状态,正常使用。

第一次使用行移动为什么对索引没有影响呢,因为使用shrink收缩表空间维护索引不受影响。
但是需要注意的是,当使用move以后,索引是失效的,需要重新rebuild索引。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31392094/viewspace-2126490/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 生成AWR性能报告
请登录后发表评论 登录
全部评论

注册时间:2016-09-06

  • 博文量
    231
  • 访问量
    215126