表模型改造

来源:互联网 发布:tourex b2b2c源码 编辑:程序博客网 时间:2024/04/30 04:58
最近遇到 表改造 问题,  发表文章纪念之

 表模型设计 感觉 一项技术活,  满足不可预见的功能添加,  不可能 添加一个字段, 整个项目代码 换血。  其次性能 要求,起码保证业务常态, 和高峰状态下性能平稳。
  最牛逼的是 满足性能的可线性扩张。 

废话不说, 上干货。


现在的业务, 大概在每 20分钟左右  到一批数据,   到达数据后做 更新等操作的一系列调度流程,  等结束后, 启动删除数据流程,
 删除数据是删除  4 小时之前的数据,  次是保证  OC  表中, 只保留4小时之内的数据,  一些调度流程一般在1.5 小时结束,估测OC

中 会保留2 个流程的最新 数据, 供前段业务查询。

现在OC表的结构 

  按照  13 个地市list分区,  比如 南京, 苏州, 常州等.... 另外表中有时间片, 10分钟个时间片,  一天24 小时, 此中的时间片
 字段 OC_time  1-144 ,  而加载的一批数据 全是1个 时间片的,  比如 08:00 过来的一批数据, 这些数据时间片为 48. 

现在监控的问题
  
 一张OC表  大概 2.5个G 左右,  从现在来看水位线 高80%,  保留4 小时数据, 这些OC表从0点到4小时前的数据虽然delete 了, 但是
表上面的空快  还在。定期管理 也不现实,业务轮回太频繁。  

 监控的oracle buffer cache 中 OC表 大量的空快。 

 此时 前段 查询大概在 20多秒吧。  基本满足 用户需求, 用户偶尔反应慢。

  另外系统整体 环境,  大量的等待事件表明内存不够用, IO 繁忙, AWR 报告中此类 问题严重, 此就不具体说明了。  




更改 :

     现在 的一级分区, 不能大批量的数据 清空操作 不方便,  改成 二级分区,  truncated 二级分区管理数据, 自动回收水位。  另外 4小时 为一个范围分区。一天 6 个分区

  调度流程完成, 算出要保留的哪些分区,然后情况上一个 分区的数据, 随着业务流程轮回truncated 分区。  预计现在 2.5 G的表  能稳定 在 7到800M左右,能节约内存 ,IO等。   而前端 查询必然带地市
  字段值,也就是说 一般查询  小于100M的,所以5秒内肯定出数据,    

   本来想和原系统表  大致类似, 用 地市做一级分区的, 但是 10G数据库,  不支持 list-range 分区(要是11g多好), 故采用  range - list 分区,   分区搞好后,监控OC表的体积 果然 能稳定在
  700-800M左右,  内存中空快的数量 几乎减少90%。  果然在 先前 预计的一样。大赞!

   但是随之而来的问题, 前段页面查询效率 突然下滑,  为啥??  和解??


   原来发现 前段查询, 是查询 最大oc_time 的数据,大致的SQL,  sql:   select  count(*)  from  table_oc  where  地市=南京 and  oc_time = func_getmax_oc_time('table_oc', '南京市') and 。。。。。。
 
  我的去!!  原来 幸幸苦苦 把OC 表改成分区表, 排除所有 可能的隐患,  居然....   心里默默 责怪 领导 当时 搞 func_getmax_oc_time('table_oc', '南京市')。函数, 曾多次
 
  提醒 需要把 这个值 先查询出来, 再带入到 sql 中多好。  直接定位到具体的二级分区。  但是还是出现这样的SQL。


 如何 优化:

 
  说到这 其实有优化 经验的 都已经知道如何 优化了。  故这里简述

  从执行计划上面来看, 出现的是 以及分区定位问题,  oracle 不知道 次函数 的返回值是多少, 故需要 到所有的一级分区 去挨个  filter,  导致的问题。 也不可能改成我当时提供的

 方案。 只能 让oracle 挨个过滤,  但是这里不矛盾, 因为让oracle 挨个过滤索引。过滤完 让其 回表 到 二级分区中,  (如果是11g  不需要建索引, 具体原因省略....)


  于是 建索引  oc(oc_time,  地市) local.  看是矛盾的索引, 索引字段 全是  分区字段,oc_time 是 一级分区, 地市是 二级分区。  而且还是分区索引。 其实一点也不矛盾。

  实际的效果     select  count(*)  from  table_oc  where  地市=南京 and  oc_time = func_getmax_oc_time('table_oc', '南京市') and 。。。。。。 0.2s 


  对比之前的20s  完爆!!


  大赞.....


  至此 OC 表分区改造 完成。 

 
0 0
原创粉丝点击