今天用ADDM生成的报告发现有几个表存在较严重的segment fragment,检查发现是统计信息(statistics collection)太旧.进一步检查发现是对象收集统计信息被锁,无法收集统计信息.优化过程如下:
SQL> SELECT a.num_rows,a.avg_row_len FROM dba_tables a WHERE a.table_name='ZDRYJCXX';
NUM_ROWS AVG_ROW_LEN
---------- -----------
3015344 396 --统计信息行数
SQL> select count(*) num_rows from zdry.zdryjcxx;
NUM_ROWS
----------
909548 --实际行数
SQL> exec dbms_stats.gather_table_stats(ZDRY,'ZDRYJCXX');
BEGIN dbms_stats.gather_table_stats(ZDRY,'ZDRYJCXX'); END;
*
第 1 行出现错误:
ORA-06550: 第 1 行, 第 37 列:
PLS-00201: 必须声明标识符 'ZDRY'
ORA-06550: 第 1 行, 第 7 列:
PL/SQL: Statement ignored
SQL> exec dbms_stats.gather_table_stats('ZDRY','ZDRYJCXX');
BEGIN dbms_stats.gather_table_stats('ZDRY','ZDRYJCXX'); END;
*
第 1 行出现错误:
ORA-20005: object statistics are locked (stattype = ALL)
ORA-06512: 在 "SYS.DBMS_STATS", line 13056
ORA-06512: 在 "SYS.DBMS_STATS", line 13076
ORA-06512: 在 line 1
SQL> show parameter statistics
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
statistics_level string TYPICAL
timed_os_statistics integer 0
timed_statistics boolean TRUE
SQL> exec dbms_stats.gather_table_stats('ZDRY','ZDRYJCXX',cascade=>true)
BEGIN dbms_stats.gather_table_stats('ZDRY','ZDRYJCXX',cascade=>true); END;
*
第 1 行出现错误:
ORA-20005: object statistics are locked (stattype = ALL)
ORA-06512: 在 "SYS.DBMS_STATS", line 13056
ORA-06512: 在 "SYS.DBMS_STATS", line 13076
ORA-06512: 在 line 1
SQL> exec dbms_stats.gather_table_stats('ZDRY','ZDRYJCXX')
BEGIN dbms_stats.gather_table_stats('ZDRY','ZDRYJCXX'); END;
*
第 1 行出现错误:
ORA-20005: object statistics are locked (stattype = ALL)
ORA-06512: 在 "SYS.DBMS_STATS", line 13056
ORA-06512: 在 "SYS.DBMS_STATS", line 13076
ORA-06512: 在 line 1
SQL> exec dbms_stats.unlock_table_stats('ZDRY','ZDRYJCXX');
--解锁统计信息
PL/SQL 过程已成功完成。
SQL> exec dbms_stats.gather_table_stats('ZDRY','ZDRYJCXX')
PL/SQL 过程已成功完成。
SQL> SELECT a.num_rows,a.avg_row_len FROM dba_tables a WHERE a.table_name='ZDRYJCXX';
NUM_ROWS AVG_ROW_LEN
---------- -----------
909548 397
SQL> select count(*) num_rows from zdry.zdryjcxx;
NUM_ROWS
----------
909548 --收集statistics后行数一样
SQL> select /*+ rule */ a.owner, a.segment_name, a.segment_type, round(a.bytes/1024/1024,0) "MB",
2 round((a.bytes-(b.num_rows*b.avg_row_len) )/1024/1024,0) WASTED from dba_segments a, dba_tables b
3 where a.owner=b.owner and a.owner not like 'SYS%' and a.segment_name = b.table_name
4 and a.segment_type='TABLE' group by a.owner, a.segment_name, a.segment_type, round(a.bytes/1024/1024,0) ,round((a.bytes-(b.num_rows*b.avg_row_len) )/1024/1024,0)
5 having round(bytes/1024/1024,0) >100
6 order by round(bytes/1024/1024,0) desc;
OWNER
------------------------------
SEGMENT_NAME
--------------------------------------------------------------------------------
SEGMENT_TYPE MB WASTED
------------------ ---------- ----------
ZDRY
ZDRYJCXX
TABLE 408 64
ZDRY
ZDRYCKYJCZFK
TABLE 144 -613
OWNER
------------------------------
SEGMENT_NAME
--------------------------------------------------------------------------------
SEGMENT_TYPE MB WASTED
------------------ ---------- ----------
SQL> alter table zdryjcxx shrink space;
alter table zdryjcxx shrink space
*
第 1 行出现错误:
ORA-00942: 表或视图不存在
SQL> alter table zdry.zdryjcxx shrink space;
alter table zdry.zdryjcxx shrink space
*
第 1 行出现错误:
ORA-10636: ROW MOVEMENT is not enabled
SQL> alter table zdry.zdryjcxx enable row movement;
表已更改。
SQL> alter table zdry.zdryjcxx shrink space;
表已更改。
SQL> select /*+ rule */ a.owner, a.segment_name, a.segment_type, round(a.bytes/1024/1024,0) "MB",
2 round((a.bytes-(b.num_rows*b.avg_row_len) )/1024/1024,0) WASTED from dba_segments a, dba_tables b
3 where a.owner=b.owner and a.owner not like 'SYS%' and a.segment_name = b.table_name
4 and a.segment_type='TABLE' group by a.owner, a.segment_name, a.segment_type, round(a.bytes/1024/1024,0) ,round((a.bytes-(b.num_rows*b.avg_row_len) )/1024/1024,0)
5 having round(bytes/1024/1024,0) >100
6 order by round(bytes/1024/1024,0) desc;
OWNER
------------------------------
SEGMENT_NAME
--------------------------------------------------------------------------------
SEGMENT_TYPE MB WASTED
------------------ ---------- ----------
ZDRY
ZDRYJCXX
TABLE 408 64
ZDRY
ZDRYCKYJCZFK
TABLE 144 -613
OWNER
------------------------------
SEGMENT_NAME
--------------------------------------------------------------------------------
SEGMENT_TYPE MB WASTED
------------------ ---------- ----------
SQL> alter table zdry.zdryjcxx shrink space;
表已更改。
SQL> alter table zdry.zdryjcxx shrink space;
表已更改。
SQL> select /*+ rule */ a.owner, a.segment_name, a.segment_type, round(a.bytes/1024/1024,0) "MB",
2 round((a.bytes-(b.num_rows*b.avg_row_len) )/1024/1024,0) WASTED from dba_segments a, dba_tables b
3 where a.owner=b.owner and a.owner not like 'SYS%' and a.segment_name = b.table_name
4 and a.segment_type='TABLE' group by a.owner, a.segment_name, a.segment_type, round(a.bytes/1024/1024,0) ,round((a.bytes-(b.num_rows*b.avg_row_len) )/1024/1024,0)
5 having round(bytes/1024/1024,0) >100
6 order by round(bytes/1024/1024,0) desc;
OWNER
------------------------------
SEGMENT_NAME
--------------------------------------------------------------------------------
SEGMENT_TYPE MB WASTED
------------------ ---------- ----------
ZDRY
ZDRYJCXX
TABLE 408 64
--试了几次shrink space优化后大小都没有变化 。说明其实不存在segment fragment, 是由于统计信息陈旧导致optimizer误判。
ZDRY
ZDRYCKYJCZFK
TABLE 144 -613
OWNER
------------------------------
SEGMENT_NAME
--------------------------------------------------------------------------------
SEGMENT_TYPE MB WASTED
------------------ ---------- ----------
SQL> alter table zdry.zdryjcxx disable row movement;
表已更改。
SQL> select /*+ rule */ a.owner, a.segment_name, a.segment_type, round(a.bytes/1024/1024,0) "MB",
2 round((a.bytes-(b.num_rows*b.avg_row_len) )/1024/1024,0) WASTED from dba_segments a, dba_tables b
3 where a.owner=b.owner and a.owner not like 'SYS%' and a.segment_name = b.table_name
4 and a.segment_type='TABLE' group by a.owner, a.segment_name, a.segment_type, round(a.bytes/1024/1024,0) ,round((a.bytes-(b.num_rows*b.avg_row_len) )/1024/1024,0)
5 having round(bytes/1024/1024,0) >100
6 order by round(bytes/1024/1024,0) desc;
OWNER
------------------------------
SEGMENT_NAME
--------------------------------------------------------------------------------
SEGMENT_TYPE MB WASTED
------------------ ---------- ----------
ZDRY
ZDRYJCXX
TABLE 408 64
ZDRY
ZDRYCKYJCZFK
TABLE 144 -613
OWNER
------------------------------
SEGMENT_NAME
--------------------------------------------------------------------------------
SEGMENT_TYPE MB WASTED
------------------ ---------- ----------
SQL> SELECT a.num_rows,a.avg_row_len FROM dba_tables a WHERE a.table_name='ZDRYCKYJCZFK';
NUM_ROWS AVG_ROW_LEN
---------- -----------
1262022 629 --统计信息行数
SQL> SELECT COUNT(*) FROM ZDRYCKYJCZFK;
SELECT COUNT(*) FROM ZDRYCKYJCZFK
*
第 1 行出现错误:
ORA-00942: 表或视图不存在
SQL> SELECT COUNT(*) FROM zdry.ZDRYCKYJCZFK;
COUNT(*)
----------
60 --实际行数
SQL> exec dbms_stats.gather_table_stats('ZDRY','ZDRYCKYJCZFK');
BEGIN dbms_stats.gather_table_stats('ZDRY','ZDRYCKYJCZFK'); END;
*
第 1 行出现错误:
ORA-20005: object statistics are locked (stattype = ALL)
ORA-06512: 在 "SYS.DBMS_STATS", line 13056
ORA-06512: 在 "SYS.DBMS_STATS", line 13076
ORA-06512: 在 line 1
SQL> analyze table zdry.ZDRYCKYJCZFK compute statistics;
analyze table zdry.ZDRYCKYJCZFK compute statistics
*
第 1 行出现错误:
ORA-38029: 对象统计信息已锁定
SQL> select owner, table_name, stattype_locked from dba_tab_statistics where stattype_locked is not null;
OWNER TABLE_NAME STATT
------------------------------ ------------------------------ -----
ZDRY ZDRYLKYJZLXX ALL
ZDRY ZDRYLKBKZXZT ALL
ZDRY ZDRYLKBKZLFBSPXX ALL
ZDRY ZDRYLKBKZLFBZXZT ALL
ZDRY ZDRYLKBKZLFB ALL
ZDRY ZDRYLKBKYWB ALL
ZDRY ZDRYLKBKQSXX ALL
ZDRY ZDRYLKBKCZFK ALL
ZDRY ZDRYLKBKZLXX ALL
ZDRY ZDRYLBBJ ALL
ZDRY ZDRYCKYJZXZT ALL
OWNER TABLE_NAME STATT
------------------------------ ------------------------------ -----
ZDRY ZDRYCKYJQBQS ALL
ZDRY ZDRYCKYJCZSZ ALL
ZDRY ZDRYCKYJCZFKSPXX ALL
ZDRY ZDRYCKYJCZFK ALL
ZDRY XXBKZXJGTSRZ ALL
ZDRY XXBKZLTJRZ ALL
ZDRY XXBKZLJSFWRZ ALL
ZDRY XXBKJGCXQQRZ ALL
ZDRY XXBKJGCXFWRZ ALL
ZDRY TRANSFER_OBJECT_LOG ALL
ZDRY TRANSFER_OBJECT_HISTORY ALL
……
已选择1191行。1191个对象统计信息被锁,由于应用程序在使用造成的.
SQL>
SQL> l
1* select owner, table_name, stattype_locked from dba_tab_statistics where stattype_locked is not null
SQL> exec dbms_stats.unlock_table_stats('ZDRY','ZDRYCKYJCZFK');
PL/SQL 过程已成功完成。
SQL> exec dbms_stats.gather_table_stats('ZDRY','ZDRYCKYJCZFK');
PL/SQL 过程已成功完成。
SQL> SELECT a.num_rows,a.avg_row_len FROM dba_tables a WHERE a.table_name='ZDRYCKYJCZFK';
NUM_ROWS AVG_ROW_LEN
---------- -----------
60 633
SQL> SELECT COUNT(*) FROM ZDRYCKYJCZFK;
SELECT COUNT(*) FROM ZDRYCKYJCZFK
*
第 1 行出现错误:
ORA-00942: 表或视图不存在
SQL> SELECT COUNT(*) FROM zdry.ZDRYCKYJCZFK;
COUNT(*)
----------
60
SQL> SELECT owner,segment_name,BYTEs/1024/1024 "MB" FROM dba_segments t WHERE t.segment_name='ZDRYCKYJCZFK' AND t.owner='ZDRY';
OWNER
------------------------------
SEGMENT_NAME
--------------------------------------------------------------------------------
MB
----------
ZDRY
ZDRYCKYJCZFK
144 --shrink space优化前144MB
SQL> alter table zdry.zdryckyjczfk enable row movement;
表已更改。
SQL> alter table zdry.zdryckyjczfk shrink space;
表已更改。
SQL> set timing on;
SQL> SELECT owner,segment_name,BYTEs/1024/1024 "MB" FROM dba_segments t WHERE t.segment_name='ZDRYCKYJCZFK' AND t.owner='ZDRY';
OWNER
------------------------------
SEGMENT_NAME
--------------------------------------------------------------------------------
MB
----------
ZDRY
ZDRYCKYJCZFK
.0625 -- shrink space优化后仅有0.0625MB,说明确实存在较严重的segment fragment.
已用时间: 00: 00: 00.01
SQL> alter table zdry.zdryckyjczfk disable row movement;
表已更改。
已用时间: 00: 00: 00.03
SQL> spool off;
结论:
有时ADDM报告的内容不一定是实事,只是表面现象.不过我们可以通过表面现象找出真正的性能问题.
[@more@]来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/16298743/viewspace-1048052/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/16298743/viewspace-1048052/