变态方式实现大数据量转换的小表热点盘问题
Posted 笑扯风云蛋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了变态方式实现大数据量转换的小表热点盘问题相关的知识,希望对你有一定的参考价值。
遇到一个认为有点奇怪的问题。
有两个表,大概都是3亿左右的数据,A表有A1字段 B表有B1字段,都是通过其他表来更新的。分别为A1使用C表,B1使用D表,不同的是C表很小只有近1万行,D表很大,也有3亿。(C表后面成为小表,D表成为大表)
因为B表有3亿数据,需要从D表这个3亿数据来获取更新,开始的时候我很为这个担心,打算给D表分表来做,但是实际测试了一下,发现居然B更新的比A表快。百思不得其解。去请教DBA,分析后发现存在热点盘问题。
因为我更新的时候,都是根据索引字段分模来更新的,每个表都分了50个左右的模,由于更新的时候读小表的时候,每次基本都会读到相同的磁盘,所以就存在热点,而读大表的时候,读到相同磁盘的概率就很低,这样,B表的更新就会比A表快了。
虽然有点变扭,但是原因确实应该就是这样。但是如何解决呢?
我想到的第一种方式,就是把小表的数据keep进缓存中,也就是说,访问小表的时候,尽快使用数据库的缓存(可以参见https://www.cnblogs.com/Richardzhu/p/3437925.html)
按照这篇文章的指引我将小表搞进了内存中,效率虽然有一点提升,但是效果并不明显。这个原因我还是没想清楚到底为什么。
第二种方式,按照DBA的指点,我把小表的pctfree(可以参见https://www.cnblogs.com/linjiqin/archive/2012/01/16/2323320.html)改大,改为了70,这样能够使表存储的更加分散,可能因为我这个表实在太小,这个基本没起啥作用。
最后实在是没辙,就想到,既然是分模导致的问题,为啥不直接把这个表按照分模逻辑再拆分?这样,访问的时候就会更加分散,我将小表增加了分模的字段,直接复制了50份,原来索引,增加取模ID建为复合索引。同样再做拆分,将表keep进缓存中。
--表
create table prod_attr_spec_on_mod pctfree 70 as select * from prod_attr_spec where 1=2 ;
alter table prod_attr_spec_on_mod add TABLE_NAME VARCHAR2(50);
alter table prod_attr_spec_on_mod add FUN_NAME VARCHAR2(100);
alter table prod_attr_spec_on_mod add PROCESS_MOD_NUM number;
declare
i number ;
begin
for i in 0..50 loop
insert into prod_attr_spec_on_mod
select t.* ,
\'SERV_ATTR\',\'GET_PRODUCT_ATTR_ID_BY_OLD_ONMOD\',i
from prod_attr_spec t ;
commit ;
end loop;
end ;
--索引
create index IDX_PRIDATTRIDPRODATTRonmod on prod_attr_spec_on_mod (attr_id ,PROCESS_MOD_NUM) ;
--keep 进内存
alter table prod_attr_spec_on_mod storage(buffer_pool keep);
alter INDEX IDX_PRIDATTRIDPRODATTRonmod STORAGE (BUFFER_POOL KEEP);
Alter table prod_attr_spec_on_mod cache;
--表分析
begin
dbms_stats.gather_table_stats
(ownname => \'GJ_USER\',
tabname => \'prod_attr_spec_on_mod\',
estimate_percent=> 100,
method_opt => \'for all columns\',
cascade => true,
degree =>16
);
end ;
这样做了以后,效率提升了一倍还多,方法确实是比较变态,但是还是挺实用的。
以上是关于变态方式实现大数据量转换的小表热点盘问题的主要内容,如果未能解决你的问题,请参考以下文章