行遷移和行連結的檢測

maojinyu發表於2011-09-09

透過前面的介紹我們知道,行連結主要是由於資料庫的db_block_size不夠大,對於一些大的欄位沒法在一個block中儲存下,從而產生了 行連結。對於行連結我們除了增大db_block_size之外沒有別的任何辦法去避免,但是因為資料庫建立後db_block_size是不可改變的 (在9i之前),對於Oracle9i的資料庫我們可以對不同的表空間指定不同的db_block_size,因此行連結的產生幾乎是不可避免的,也沒有 太多可以調整的地方。行遷移則主要是由於更新表的時候,由於表的pctfree引數設定太小,導致block中沒有足夠的空間去容納更新後的記錄,從而產 生了行遷移。對於行遷移來說就非常有調整的必要了,因為這個是可以調整和控制清除的。

如何檢測資料庫中存在有了行遷移和行連結呢?我們可以利用Oracle資料庫自身提供的指令碼 utlchain.sql(在$ORACLE_HOME/rdbms/admin目錄下)生成chained_rows表,然後利用ANALYZE TABLE table_name LIST CHAINED ROWS INTO chained_rows命令逐個分析表,將分析的結果存入chained_rows表中。從utlchain.sql指令碼中我們看到 chained_rows的建表指令碼,對於分割槽表,cluster表都是適用的。然後可以使用拼湊語句的辦法生成分析所需要的表的指令碼,並執行指令碼將具體 的分析資料放入Chained_rows表中,例如下面是分析一個使用者下所有表的指令碼:

SPOOL list_migation_rows.sql

SET ECHO OFF

SET HEADING OFF

SELECT 'ANALYZE TABLE ' || table_name ||

' LIST CHAINED ROWS INTO chained_rows;' FROM user_tables;

SPOOL OFF

然後查詢chained_rows表,可以具體檢視某張表上有多少的行連結和行遷移。

SELECT table_name, count(*) from chained_rows GROUP BY table_name;

當然,也可以查詢v$sysstat檢視中的’table fetch continued row’列得到當前的行連結和行遷移數量。

SELECT name, value FROM v$sysstat WHERE name = 'table fetch continued row';

可以使用如下的指令碼來直接查詢存在有行連結和行遷移的表,自動完成所有的分析和統計。

accept owner prompt " Enter the schema name

to check for Row Chaining (RETURN for All): "

prompt

prompt

accept table prompt " Enter the table name

to check (RETURN for All tables owned by &owner): "

prompt

prompt

set head off serverout on term on feed off veri off echo off

!clear

prompt

declare

v_owner varchar2(30);

v_table varchar2(30);

v_chains number;

v_rows number;

v_count number := 0;

sql_stmt varchar2(100);

dynamicCursor INTEGER;

dummy INTEGER;

cursor chains is

select count(*) from chained_rows;

cursor analyze is

select owner, table_name

from sys.dba_tables

where owner like upper('%&owner%')

and table_name like upper('%&table%')

order by table_name;

begin

dbms_output.enable(64000);

open analyze;

fetch analyze into v_owner, v_table;

while analyze%FOUND loop

dynamicCursor := dbms_sql.open_cursor;

sql_stmt := 'analyze table '||v_owner

||'.'||v_table||' list chained rows into chained_rows';

dbms_sql.parse(dynamicCursor, sql_stmt, dbms_sql.native);

dummy := dbms_sql.execute(dynamicCursor);

dbms_sql.close_cursor(dynamicCursor);

open chains;

fetch chains into v_chains;

if (v_chains != 0) then

if (v_count = 0) then

dbms_output.put_line(CHR(9)||CHR(9)||CHR(9)

||'<<<<< Chained Rows Found >>>>>');

v_count := 1;

end if;

dynamicCursor := dbms_sql.open_cursor;

sql_stmt := 'Select count(*) v_rows'||' From '||v_owner||'.'||v_table;

dbms_sql.parse(dynamicCursor, sql_stmt, dbms_sql.native);

dbms_sql.DEFINE_COLUMN(dynamicCursor, 1, v_rows);

dummy := dbms_sql.execute(dynamicCursor);

dummy := dbms_sql.fetch_rows(dynamicCursor);

dbms_sql.COLUMN_VALUE(dynamicCursor, 1, v_rows);

dbms_sql.close_cursor(dynamicCursor);

dbms_output.put_line(v_owner||'.'||v_table);

dbms_output.put_line(CHR(9)||'---&gt Has '

||v_chains||' Chained Rows and '||v_rows||' Num_Rows in it!');

dynamicCursor := dbms_sql.open_cursor;

sql_stmt := 'truncate table chained_rows';

dbms_sql.parse(dynamicCursor, sql_stmt, dbms_sql.native);

dummy := dbms_sql.execute(dynamicCursor);

dbms_sql.close_cursor(dynamicCursor);

v_chains := 0;

end if;

close chains;

fetch analyze into v_owner, v_table;

end loop;

if (v_count = 0) then

dbms_output.put_line('No Chained Rows found

in the '||v_owner||' owned Tables!');

end if;

close analyze;

end;

/

set feed on head on

prompt

[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9907339/viewspace-1054894/,如需轉載,請註明出處,否則將追究法律責任。

相關文章