什么是SQL行迁移和行链接
本篇内容介绍了“什么是SQL行迁移和行链接”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
行迁移和行链接(行的跨块存储)行链接:
成因:指一行存储在多个块中的情况,即行链接是跨越多块的行。
第一次插入时,一个块存不下,insert 到多个块中。
当一行数据大于一个数据块,ORACLE会同时分配两个数据块,并在第一个块上登记第二个块的地址,从而形成行链接。
后果:导致应用需要访问更多的数据块,性能下降。
预防:针对表空间扩大数据块大小。
检查:analyze table 表名 validate structure cascade into chained_rows;
需要执行脚本$ORACLE_HOME/rdbms/admin/utlchain.sql创建chained_rows表。
行迁移:
成因:当行被Update时,如果Update更新的行大于数据块得PCTFREE值,就需要申请第2个块,从而形成行迁移。
当一个数据行由于 update 语句导致当前块被重新定位到另一个块(那里有充足的空间)中,但在原始块中会保留一个指针。
原始块中的指针是必需的,因为索引的 ROWID 项仍然指向原始位置。
行迁移是 update 语句当 pctfree 空间不足时引起的,它与 insert 和 delete 语句无关。
后果:导致应用需要访问更多的数据块,性能下降。
预防:1. 将数据块的PCTFREE调大;
2. 针对表空间扩大数据块大小
检查:analyze table 表名 validate structure cascade into chained_rows;
如何知道发生了行链接或行迁移?
对表进行analyze,然后查看 dba_tables 的 AVG_ROW_LEN 列和 CHAIN_CNT 列,若不为0,则说明发生了行迁移或者行链接。
如何确定发生了行迁移还是行链接?
这里采用move的办法:
若对表进行move,然后CHAIN_CNT的列变为0,并且blocks也会减少,则说明只发生了行迁移。
若对表进行move,然后CHAIN_CNT的列不变,并且blocks也不变,则说明只发生了行链接。
还有一种特殊情况,同时发生行迁移和行链接(比较极端):
在对表进行update时,更新的行过大,导致一个块存不下,那么会变成行迁移,但是由于过大,因此还需要更多的块来存储,发生的是行链接
若对表进行move,然后CHAIN_CNT的列不变或者减少,并且blocks减少,则说明同时发生了行链接和行链接。
优化:
行迁移:1、若表在进行update时发生了行迁移,那么需要对表进行move操作(若有索引,需要重建)
2、exp/imp方式(针对发生行迁移的表)
3、对发生行迁移的表的数据进行新建临时表,然后在把记录插回到原表
行链接:只有通过加大BLOCK块的方式才可以避免
行迁移测试:创建表SQL>droptablet1;Tabledropped.SQL>createtablet1(c1varchar2(20));Tablecreated.插入数据SQL>insertintot1select''fromdualconnectbylevel<1000;999rowscreated.SQL>commit;Commitcomplete.先分析一下t1表,确定无行迁移SQL>selectpct_free,pct_used,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T1';PCT_FREEPCT_USEDAVG_ROW_LENCHAIN_CNTBLOCKS---------------------------------------------------10SQL>analyzetablet1computestatistics;Tableanalyzed.SQL>selectpct_free,pct_used,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T1';PCT_FREEPCT_USEDAVG_ROW_LENCHAIN_CNTBLOCKS---------------------------------------------------10305使用了5个块,并且chain_cnt为0,并没有发生行迁移。update空列,再分析t1,有了行迁移SQL>updatet1setc1='oraclemysql';999rowsupdated.SQL>commit;Commitcomplete.SQL>selectpct_free,pct_used,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T1';PCT_FREEPCT_USEDAVG_ROW_LENCHAIN_CNTBLOCKS---------------------------------------------------10305SQL>analyzetablet1computestatistics;Tableanalyzed.SQL>selectpct_free,pct_used,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T1';PCT_FREEPCT_USEDAVG_ROW_LENCHAIN_CNTBLOCKS---------------------------------------------------102176713说明999行中有767行发生了行迁移,使用的块也增加了。消除行迁移:
这里使用 move 解决,若表上有索引,需要重建索引,move会使表上的索引失效:
SQL>altertablet1move;Tablealtered.move表后,再分析t1,行迁移消失。SQL>selectpct_free,pct_used,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T1';PCT_FREEPCT_USEDAVG_ROW_LENCHAIN_CNTBLOCKS---------------------------------------------------102176713SQL>analyzetablet1computestatistics;Tableanalyzed.SQL>selectpct_free,pct_used,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T1';PCT_FREEPCT_USEDAVG_ROW_LENCHAIN_CNTBLOCKS---------------------------------------------------101606
使用了6个块,从13块变成6,block减少,并且CHAIN_CNT由767变成0,此时已经消除了行迁移。
总结:若表在进行update时发生了行迁移,那么需要对表进行行迁移的消除,可以采用move操作来消除行迁移(若有索引,需要重建)。
行链接测试:创建表SQL>createtablet2(c1varchar2(4000),c2varchar2(4000),c3varchar2(4000));Tablecreated.插入数据SQL>insertintot2select'a','b','c'fromdualconnectbylevel<=100;100rowscreated.SQL>commit;Commitcomplete.先分析一下t1表,确定无行链接SQL>selectpct_free,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T2';PCT_FREEAVG_ROW_LENCHAIN_CNTBLOCKS-----------------------------------------10SQL>analyzetablet2computestatistics;Tableanalyzed.SQL>selectpct_free,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T2';PCT_FREEAVG_ROW_LENCHAIN_CNTBLOCKS-----------------------------------------10905使用了5个块,并且chain_cnt为0,并没有发生行链接。插入大于8K行,再分析t2,有了行链接SQL>insertintot2values(lpad('a',4000,'a'),lpad('a',4000,'a'),lpad('a',4000,'a'));1rowcreated.SQL>commit;Commitcomplete.SQL>selectpct_free,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T2';PCT_FREEAVG_ROW_LENCHAIN_CNTBLOCKS-----------------------------------------10905SQL>analyzetablet2computestatistics;Tableanalyzed.SQL>selectpct_free,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T2';PCT_FREEAVG_ROW_LENCHAIN_CNTBLOCKS-----------------------------------------1012815
说明 新插入的 1 行数据发生了行迁移,使用的块不变。
消除行链接:创建非标准块大小表空间16KSQL>showparametercacheNAMETYPEVALUE-----------------------------------------------------------------------------client_result_cache_lagbiginteger3000client_result_cache_sizebiginteger0db_16k_cache_sizebiginteger0db_2k_cache_sizebiginteger0db_32k_cache_sizebiginteger1Gdb_4k_cache_sizebiginteger0db_8k_cache_sizebiginteger0db_cache_advicestringONdb_cache_sizebiginteger0db_flash_cache_filestringdb_flash_cache_sizebiginteger0db_keep_cache_sizebiginteger0db_recycle_cache_sizebiginteger0object_cache_max_size_percentinteger10object_cache_optimal_sizeinteger102400result_cache_max_resultinteger5result_cache_max_sizebiginteger12064Kresult_cache_modestringMANUALresult_cache_remote_expirationinteger0session_cached_cursorsinteger50设置db_16k_cache_size为16mSQL>altersystemsetdb_16k_cache_size=16m;Systemaltered.创建表空间createtablespacetabspace_16kblocksize16Kdatafile'/oracle/app/oracle/oradata/test/tabspace_16k.dbf'size20Mautoextendonextentmanagementlocalsegmentspacemanagementauto;把t2表移动到tabspace_16k表空间上SQL>altertablet2movetablespacetabspace_16k;Tablealtered.再次进行分析查看SQL>selectpct_free,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T2';PCT_FREEAVG_ROW_LENCHAIN_CNTBLOCKS-----------------------------------------1012815SQL>analyzetablet2computestatistics;Tableanalyzed.SQL>selectpct_free,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T2';PCT_FREEAVG_ROW_LENCHAIN_CNTBLOCKS-----------------------------------------1012804
目前使用了4个块,并且chain_cnt为0,说明行链接已经消除了。
同时发生行迁移和行链接(比较极端):创建表SQL>droptablet3;Tabledropped.SQL>createtablet3(c1int,c2varchar2(4000),c3varchar2(4000),c4varchar2(4000),c5varchar2(4000));Tablecreated.插入数据SQL>insertintot3selectlevel,'','','',''fromdualconnectbylevel<=100;100rowscreated.SQL>commit;Commitcomplete.先分析一下t3表,确定无行迁移和行链接SQL>selectpct_free,pct_used,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T3';PCT_FREEPCT_USEDAVG_ROW_LENCHAIN_CNTBLOCKS---------------------------------------------------10SQL>analyzetablet3computestatistics;Tableanalyzed.SQL>selectpct_free,pct_used,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T3';PCT_FREEPCT_USEDAVG_ROW_LENCHAIN_CNTBLOCKS---------------------------------------------------10605使用了5个块,并且chain_cnt为0,并没有发生行迁移或者行链接对列进行更新,再分析t1,有了行迁移或者行链接SQL>updatet3setc2=LPAD('1',4000,'*'),c3=LPAD('1',4000,'*'),c4=LPAD('1',4000,'*'),c5=LPAD('1',4000,'*');100rowsupdated.SQL>commit;Commitcomplete.SQL>selectpct_free,pct_used,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T3';PCT_FREEPCT_USEDAVG_ROW_LENCHAIN_CNTBLOCKS---------------------------------------------------10605SQL>analyzetablet3computestatistics;Tableanalyzed.SQL>selectpct_free,pct_used,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T3';PCT_FREEPCT_USEDAVG_ROW_LENCHAIN_CNTBLOCKS---------------------------------------------------1016030100496
说明 100 行中有 100 行发生了行迁移或者行链接,使用的块也增加了。
如何确定是发生了行迁移还是行链接?这里采用move的办法:
若对表进行move,然后CHAIN_CNT的列变为0,并且blocks也会减少,则说明只发生了行迁移。
若对表进行move,然后CHAIN_CNT的列不变,并且blocks也不变,则说明只发生了行链接。
还有一种特殊情况,同时发生行迁移和行链接(比较极端):
在对表进行update时,更新的行过大,导致一个块存不下,那么会变成行迁移,但是由于过大,因此还需要更多的块来存储,发生的是行链接
若对表进行move,然后CHAIN_CNT的列不变或者减少,并且blocks减少,则说明同时发生了行链接和行链接。
消除行迁移:这里使用move解决,若表上有索引,需要重建索引,move会使表上的索引失效:SQL>altertablet3move;Tablealtered.move表后,再分析t3SQL>selectpct_free,pct_used,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T3';PCT_FREEPCT_USEDAVG_ROW_LENCHAIN_CNTBLOCKS---------------------------------------------------1016030100496SQL>analyzetablet3computestatistics;Tableanalyzed.SQL>selectpct_free,pct_used,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T3';PCT_FREEPCT_USEDAVG_ROW_LENCHAIN_CNTBLOCKS---------------------------------------------------1016044100234
使用了234个块,从496块变成234,block减少,并且CHAIN_CNT没变,说明已经消除了行迁移,但是还有行链接为消除。
因此,同时发生行迁移和行链接。
下一步需要消除行链接:和正常消除行链接的方法一致:
创建非标准块大小表空间16KSQL>showparametercacheNAMETYPEVALUE-----------------------------------------------------------------------------client_result_cache_lagbiginteger3000client_result_cache_sizebiginteger0db_16k_cache_sizebiginteger0db_2k_cache_sizebiginteger0db_32k_cache_sizebiginteger1Gdb_4k_cache_sizebiginteger0db_8k_cache_sizebiginteger0db_cache_advicestringONdb_cache_sizebiginteger0db_flash_cache_filestringdb_flash_cache_sizebiginteger0db_keep_cache_sizebiginteger0db_recycle_cache_sizebiginteger0object_cache_max_size_percentinteger10object_cache_optimal_sizeinteger102400result_cache_max_resultinteger5result_cache_max_sizebiginteger12064Kresult_cache_modestringMANUALresult_cache_remote_expirationinteger0session_cached_cursorsinteger50设置db_16k_cache_size为16mSQL>altersystemsetdb_16k_cache_size=16m;Systemaltered.创建表空间createtablespacetabspace_16kblocksize16Kdatafile'/oracle/app/oracle/oradata/test/tabspace_16k.dbf'size20Mautoextendonextentmanagementlocalsegmentspacemanagementauto;把t2表移动到tabspace_16k表空间上SQL>altertablet3movetablespacetabspace_16k;Tablealtered.再次进行分析查看SQL>selectpct_free,pct_used,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T3';PCT_FREEPCT_USEDAVG_ROW_LENCHAIN_CNTBLOCKS---------------------------------------------------1016044100234SQL>analyzetablet3computestatistics;Tableanalyzed.SQL>selectpct_free,pct_used,avg_row_len,chain_cnt,blocksfromuser_tableswheretable_name='T3';PCT_FREEPCT_USEDAVG_ROW_LENCHAIN_CNTBLOCKS---------------------------------------------------10160180107
目前使用了107个块,并且chain_cnt为0,说明行链接已经消除了。
至此消除了行迁移和行链接。
“什么是SQL行迁移和行链接”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。