您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“什么是SQL行遷移和行鏈接”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
行鏈接:
成因:指一行存儲(chǔ)在多個(gè)塊中的情況,即行鏈接是跨越多塊的行。
第一次插入時(shí),一個(gè)塊存不下,insert 到多個(gè)塊中。
當(dāng)一行數(shù)據(jù)大于一個(gè)數(shù)據(jù)塊,ORACLE會(huì)同時(shí)分配兩個(gè)數(shù)據(jù)塊,并在第一個(gè)塊上登記第二個(gè)塊的地址,從而形成行鏈接。
后果:導(dǎo)致應(yīng)用需要訪問(wèn)更多的數(shù)據(jù)塊,性能下降。
預(yù)防:針對(duì)表空間擴(kuò)大數(shù)據(jù)塊大小。
檢查:analyze table 表名 validate structure cascade into chained_rows;
需要執(zhí)行腳本$ORACLE_HOME/rdbms/admin/utlchain.sql創(chuàng)建chained_rows表。
行遷移:
成因:當(dāng)行被Update時(shí),如果Update更新的行大于數(shù)據(jù)塊得PCTFREE值,就需要申請(qǐng)第2個(gè)塊,從而形成行遷移。
當(dāng)一個(gè)數(shù)據(jù)行由于 update 語(yǔ)句導(dǎo)致當(dāng)前塊被重新定位到另一個(gè)塊(那里有充足的空間)中,但在原始?jí)K中會(huì)保留一個(gè)指針。
原始?jí)K中的指針是必需的,因?yàn)樗饕?ROWID 項(xiàng)仍然指向原始位置。
行遷移是 update 語(yǔ)句當(dāng) pctfree 空間不足時(shí)引起的,它與 insert 和 delete 語(yǔ)句無(wú)關(guān)。
后果:導(dǎo)致應(yīng)用需要訪問(wèn)更多的數(shù)據(jù)塊,性能下降。
預(yù)防:1. 將數(shù)據(jù)塊的PCTFREE調(diào)大;
2. 針對(duì)表空間擴(kuò)大數(shù)據(jù)塊大小
檢查:analyze table 表名 validate structure cascade into chained_rows;
如何知道發(fā)生了行鏈接或行遷移?
對(duì)表進(jìn)行analyze,然后查看 dba_tables 的 AVG_ROW_LEN 列和 CHAIN_CNT 列,若不為0,則說(shuō)明發(fā)生了行遷移或者行鏈接。
如何確定發(fā)生了行遷移還是行鏈接?
這里采用move的辦法:
若對(duì)表進(jìn)行move,然后CHAIN_CNT的列變?yōu)?,并且blocks也會(huì)減少,則說(shuō)明只發(fā)生了行遷移。
若對(duì)表進(jìn)行move,然后CHAIN_CNT的列不變,并且blocks也不變,則說(shuō)明只發(fā)生了行鏈接。
還有一種特殊情況,同時(shí)發(fā)生行遷移和行鏈接(比較極端):
在對(duì)表進(jìn)行update時(shí),更新的行過(guò)大,導(dǎo)致一個(gè)塊存不下,那么會(huì)變成行遷移,但是由于過(guò)大,因此還需要更多的塊來(lái)存儲(chǔ),發(fā)生的是行鏈接
若對(duì)表進(jìn)行move,然后CHAIN_CNT的列不變或者減少,并且blocks減少,則說(shuō)明同時(shí)發(fā)生了行鏈接和行鏈接。
優(yōu)化:
行遷移:1、若表在進(jìn)行update時(shí)發(fā)生了行遷移,那么需要對(duì)表進(jìn)行move操作(若有索引,需要重建)
2、exp/imp方式(針對(duì)發(fā)生行遷移的表)
3、對(duì)發(fā)生行遷移的表的數(shù)據(jù)進(jìn)行新建臨時(shí)表,然后在把記錄插回到原表
行鏈接:只有通過(guò)加大BLOCK塊的方式才可以避免
創(chuàng)建表 SQL> drop table t1; Table dropped. SQL> create table t1 (c1 varchar2(20)); Table created. 插入數(shù)據(jù) SQL> insert into t1 select '' from dual connect by level < 1000; 999 rows created. SQL> commit; Commit complete. 先分析一下 t1 表,確定無(wú)行遷移 SQL> select pct_free,pct_used,avg_row_len,chain_cnt,blocks from user_tables where table_name='T1'; PCT_FREE PCT_USED AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ---------- ----------- ---------- ---------- 10 SQL> analyze table t1 compute statistics; Table analyzed. SQL> select pct_free,pct_used,avg_row_len,chain_cnt,blocks from user_tables where table_name='T1'; PCT_FREE PCT_USED AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ---------- ----------- ---------- ---------- 10 3 0 5 使用了5個(gè)塊,并且chain_cnt為0,并沒(méi)有發(fā)生行遷移。 update空列,再分析 t1,有了行遷移 SQL> update t1 set c1='oracle mysql'; 999 rows updated. SQL> commit; Commit complete. SQL> select pct_free,pct_used,avg_row_len,chain_cnt,blocks from user_tables where table_name='T1'; PCT_FREE PCT_USED AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ---------- ----------- ---------- ---------- 10 3 0 5 SQL> analyze table t1 compute statistics; Table analyzed. SQL> select pct_free,pct_used,avg_row_len,chain_cnt,blocks from user_tables where table_name='T1'; PCT_FREE PCT_USED AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ---------- ----------- ---------- ---------- 10 21 767 13 說(shuō)明 999 行中有 767 行發(fā)生了行遷移,使用的塊也增加了。
這里使用 move 解決,若表上有索引,需要重建索引,move會(huì)使表上的索引失效:
SQL> alter table t1 move; Table altered. move 表后,再分析 t1,行遷移消失。 SQL> select pct_free,pct_used,avg_row_len,chain_cnt,blocks from user_tables where table_name='T1'; PCT_FREE PCT_USED AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ---------- ----------- ---------- ---------- 10 21 767 13 SQL> analyze table t1 compute statistics; Table analyzed. SQL> select pct_free,pct_used,avg_row_len,chain_cnt,blocks from user_tables where table_name='T1'; PCT_FREE PCT_USED AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ---------- ----------- ---------- ---------- 10 16 0 6
使用了6個(gè)塊,從13塊變成6,block減少,并且CHAIN_CNT由767變成0,此時(shí)已經(jīng)消除了行遷移。
總結(jié):若表在進(jìn)行update時(shí)發(fā)生了行遷移,那么需要對(duì)表進(jìn)行行遷移的消除,可以采用move操作來(lái)消除行遷移(若有索引,需要重建)。
創(chuàng)建表 SQL> create table t2 (c1 varchar2(4000),c2 varchar2(4000),c3 varchar2(4000)); Table created. 插入數(shù)據(jù) SQL> insert into t2 select 'a','b','c' from dual connect by level <= 100; 100 rows created. SQL> commit; Commit complete. 先分析一下 t1 表,確定無(wú)行鏈接 SQL> select pct_free,avg_row_len,chain_cnt,blocks from user_tables where table_name='T2'; PCT_FREE AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ----------- ---------- ---------- 10 SQL> analyze table t2 compute statistics; Table analyzed. SQL> select pct_free,avg_row_len,chain_cnt,blocks from user_tables where table_name='T2'; PCT_FREE AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ----------- ---------- ---------- 10 9 0 5 使用了5個(gè)塊,并且chain_cnt為0,并沒(méi)有發(fā)生行鏈接。 插入大于 8K 行,再分析 t2,有了行鏈接 SQL> insert into t2 values (lpad('a',4000,'a'),lpad('a',4000,'a'),lpad('a',4000,'a')); 1 row created. SQL> commit; Commit complete. SQL> select pct_free,avg_row_len,chain_cnt,blocks from user_tables where table_name='T2'; PCT_FREE AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ----------- ---------- ---------- 10 9 0 5 SQL> analyze table t2 compute statistics; Table analyzed. SQL> select pct_free,avg_row_len,chain_cnt,blocks from user_tables where table_name='T2'; PCT_FREE AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ----------- ---------- ---------- 10 128 1 5
說(shuō)明 新插入的 1 行數(shù)據(jù)發(fā)生了行遷移,使用的塊不變。
創(chuàng)建非標(biāo)準(zhǔn)塊大小表空間 16K SQL> show parameter cache NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ client_result_cache_lag big integer 3000 client_result_cache_size big integer 0 db_16k_cache_size big integer 0 db_2k_cache_size big integer 0 db_32k_cache_size big integer 1G db_4k_cache_size big integer 0 db_8k_cache_size big integer 0 db_cache_advice string ON db_cache_size big integer 0 db_flash_cache_file string db_flash_cache_size big integer 0 db_keep_cache_size big integer 0 db_recycle_cache_size big integer 0 object_cache_max_size_percent integer 10 object_cache_optimal_size integer 102400 result_cache_max_result integer 5 result_cache_max_size big integer 12064K result_cache_mode string MANUAL result_cache_remote_expiration integer 0 session_cached_cursors integer 50 設(shè)置db_16k_cache_size為16m SQL> alter system set db_16k_cache_size=16m; System altered. 創(chuàng)建表空間 create tablespace tabspace_16k blocksize 16K datafile '/oracle/app/oracle/oradata/test/tabspace_16k.dbf' size 20M autoextend on extent management local segment space management auto; 把t2表移動(dòng)到tabspace_16k表空間上 SQL> alter table t2 move tablespace tabspace_16k; Table altered. 再次進(jìn)行分析查看 SQL> select pct_free,avg_row_len,chain_cnt,blocks from user_tables where table_name='T2'; PCT_FREE AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ----------- ---------- ---------- 10 128 1 5 SQL> analyze table t2 compute statistics; Table analyzed. SQL> select pct_free,avg_row_len,chain_cnt,blocks from user_tables where table_name='T2'; PCT_FREE AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ----------- ---------- ---------- 10 128 0 4
目前使用了4個(gè)塊,并且chain_cnt為0,說(shuō)明行鏈接已經(jīng)消除了。
創(chuàng)建表 SQL> drop table t3; Table dropped. SQL> create table t3 (c1 int,c2 varchar2(4000),c3 varchar2(4000),c4 varchar2(4000),c5 varchar2(4000)); Table created. 插入數(shù)據(jù) SQL> insert into t3 select level,'','','','' from dual connect by level <= 100; 100 rows created. SQL> commit; Commit complete. 先分析一下 t3 表,確定無(wú)行遷移和行鏈接 SQL> select pct_free,pct_used,avg_row_len,chain_cnt,blocks from user_tables where table_name='T3'; PCT_FREE PCT_USED AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ---------- ----------- ---------- ---------- 10 SQL> analyze table t3 compute statistics; Table analyzed. SQL> select pct_free,pct_used,avg_row_len,chain_cnt,blocks from user_tables where table_name='T3'; PCT_FREE PCT_USED AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ---------- ----------- ---------- ---------- 10 6 0 5 使用了5個(gè)塊,并且chain_cnt為0,并沒(méi)有發(fā)生行遷移或者行鏈接 對(duì)列進(jìn)行更新,再分析 t1,有了行遷移或者行鏈接 SQL> update t3 set c2 = LPAD('1', 4000, '*'),c3 = LPAD('1', 4000, '*'),c4 = LPAD('1', 4000, '*'),c5 = LPAD('1', 4000, '*'); 100 rows updated. SQL> commit; Commit complete. SQL> select pct_free,pct_used,avg_row_len,chain_cnt,blocks from user_tables where table_name='T3'; PCT_FREE PCT_USED AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ---------- ----------- ---------- ---------- 10 6 0 5 SQL> analyze table t3 compute statistics; Table analyzed. SQL> select pct_free,pct_used,avg_row_len,chain_cnt,blocks from user_tables where table_name='T3'; PCT_FREE PCT_USED AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ---------- ----------- ---------- ---------- 10 16030 100 496
說(shuō)明 100 行中有 100 行發(fā)生了行遷移或者行鏈接,使用的塊也增加了。
這里采用move的辦法:
若對(duì)表進(jìn)行move,然后CHAIN_CNT的列變?yōu)?,并且blocks也會(huì)減少,則說(shuō)明只發(fā)生了行遷移。
若對(duì)表進(jìn)行move,然后CHAIN_CNT的列不變,并且blocks也不變,則說(shuō)明只發(fā)生了行鏈接。
還有一種特殊情況,同時(shí)發(fā)生行遷移和行鏈接(比較極端):
在對(duì)表進(jìn)行update時(shí),更新的行過(guò)大,導(dǎo)致一個(gè)塊存不下,那么會(huì)變成行遷移,但是由于過(guò)大,因此還需要更多的塊來(lái)存儲(chǔ),發(fā)生的是行鏈接
若對(duì)表進(jìn)行move,然后CHAIN_CNT的列不變或者減少,并且blocks減少,則說(shuō)明同時(shí)發(fā)生了行鏈接和行鏈接。
這里使用 move 解決,若表上有索引,需要重建索引,move會(huì)使表上的索引失效: SQL> alter table t3 move; Table altered. move 表后,再分析 t3 SQL> select pct_free,pct_used,avg_row_len,chain_cnt,blocks from user_tables where table_name='T3'; PCT_FREE PCT_USED AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ---------- ----------- ---------- ---------- 10 16030 100 496 SQL> analyze table t3 compute statistics; Table analyzed. SQL> select pct_free,pct_used,avg_row_len,chain_cnt,blocks from user_tables where table_name='T3'; PCT_FREE PCT_USED AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ---------- ----------- ---------- ---------- 10 16044 100 234
使用了234個(gè)塊,從496塊變成234,block減少,并且CHAIN_CNT沒(méi)變,說(shuō)明已經(jīng)消除了行遷移,但是還有行鏈接為消除。
因此,同時(shí)發(fā)生行遷移和行鏈接。
和正常消除行鏈接的方法一致:
創(chuàng)建非標(biāo)準(zhǔn)塊大小表空間 16K SQL> show parameter cache NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ client_result_cache_lag big integer 3000 client_result_cache_size big integer 0 db_16k_cache_size big integer 0 db_2k_cache_size big integer 0 db_32k_cache_size big integer 1G db_4k_cache_size big integer 0 db_8k_cache_size big integer 0 db_cache_advice string ON db_cache_size big integer 0 db_flash_cache_file string db_flash_cache_size big integer 0 db_keep_cache_size big integer 0 db_recycle_cache_size big integer 0 object_cache_max_size_percent integer 10 object_cache_optimal_size integer 102400 result_cache_max_result integer 5 result_cache_max_size big integer 12064K result_cache_mode string MANUAL result_cache_remote_expiration integer 0 session_cached_cursors integer 50 設(shè)置db_16k_cache_size為16m SQL> alter system set db_16k_cache_size=16m; System altered. 創(chuàng)建表空間 create tablespace tabspace_16k blocksize 16K datafile '/oracle/app/oracle/oradata/test/tabspace_16k.dbf' size 20M autoextend on extent management local segment space management auto; 把t2表移動(dòng)到tabspace_16k表空間上 SQL> alter table t3 move tablespace tabspace_16k; Table altered. 再次進(jìn)行分析查看 SQL> select pct_free,pct_used,avg_row_len,chain_cnt,blocks from user_tables where table_name='T3'; PCT_FREE PCT_USED AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ---------- ----------- ---------- ---------- 10 16044 100 234 SQL> analyze table t3 compute statistics; Table analyzed. SQL> select pct_free,pct_used,avg_row_len,chain_cnt,blocks from user_tables where table_name='T3'; PCT_FREE PCT_USED AVG_ROW_LEN CHAIN_CNT BLOCKS ---------- ---------- ----------- ---------- ---------- 10 16018 0 107
目前使用了107個(gè)塊,并且chain_cnt為0,說(shuō)明行鏈接已經(jīng)消除了。
至此消除了行遷移和行鏈接。
“什么是SQL行遷移和行鏈接”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。