变态方式实现大数据量转换的小表热点盘问题
遇到一个认为有点奇怪的问题。
有两个表,大概都是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 ;
这样做了以后,效率提升了一倍还多,方法确实是比较变态,但是还是挺实用的。
相关推荐
表格的现在还是较为常用的一种标签,但不是用来布局,常见处理、显示表格式数据。在HTML网页中,要想创建表格,就需要使用表格相关的标签。<table> <tr> <td>单元格内的文字</td> ...