关于修改分区表的准备和操作细则(r3笔记26天)

在之前的博文中,讨论过一个根据分区键值发现性能问题的案例。90%以上的数据都分布在了一个分区上,其它的分区要么没有数据要么数据很少,这是很明显的分区问题。当然这个过程中也发现了分区的划分从开发角度和数据角度还是存在很大的差别,导致了分区的问题。 通过分区键值发现性能问题 http://blog.itpub.net/23718752/viewspace-1263068/ 发现了问题,以点带面,发现一些相关的分区表也有类似的问题,最后确认和分析后,发现收到影响的表有20多个,而且数据量都不小。 看来又得是一个忙碌的夜晚来修复这个问题了。 如果要准备相应的脚本,也要考虑很多的问题,我大体列了几个步骤。相应的脚本也会按照这个步骤处理。 大体的思路和数据迁移有些类似,相比来说增加了分区的操作。 step1_dump_bak 关于备份,最好存有两份备份,物理备份和逻辑备份 step2_truncate 分区之前,需要清空表中的数据。这个过程中需要考虑disable foreign key和trigger. step3_drop_par 重新分区的时候,只保留一个默认分区maxvalue,然后使用drop partition命令完成。 step4_pre_par 在正式分区之前,可以先把表设为nologging,index设置为nologging,lob字段也设置为nologging.作为后面数据导入的时候的优化准备。 step5_par_one 开始正式的分区修改,这个操作依赖于默认的maxvalue分区,不断的split,因为没有了数据所以速度还是很快的。这个部分处理分区键值为一个的表 step6_par_two 开始正式的分区修改,这个部分处理分区键值为2个的表。 step7_post_par 这个部分需要在数据导入之前再次验证分区的规则和分区数据是否和预期一致,在数据导入之后检查就太晚了。 step8_data_append 确认之后,开始数据的导入,这个部分使用数据迁移中的外部表方式,速度还是很快的,在反复比较了imp/impdp,sqlldr之后,外部表处理和控制要更好一些。 step9_stat_gather 这个部分是在数据导入之后。需要重新收集统计信息,尽管表的数据条数没有变化,但是分区级的统计信息是极大的变化。这个也需要考虑。 #1 step1_dump_bak 关于备份,个人建议还是最好有两种不同的备份,比如exp/expdp一种备份,这个作为物理备份,外部表导出来作为另外一种备份,同时在数据加载的时候用到,有了这两种备份,就不会在出现问题的时候慌乱了,如果外部表导出因为空间等不可知因素,还有希望去弥补。 #step2_truncate 这个部分,就是直接truncate来完成了。可以开几个session来并行执行。 step3_drop_par 这个部分可以参考如下的脚本来完成,会删除掉其它的分区,只保留默认分区,当然如果分区规则有变化也需要适当的做一些变更。这个部分完全可以用shell写成批处理脚本。 set pages 0 set linesize 150 set feedback off select 'alter table '||table_name||' drop partition '||partition_name||' ;' from user_tab_partitions where table_name='XXXXXX' and partition_name not like '%MAXVALUE%' step4_pre_par 这个过程中需要设置表为Nologging..使用的脚本比较长,可以参考http://blog.itpub.net/23718752/viewspace-1192153/ step5_par_one step6_par_two 关于分区的修改部分,之前自己写了一个Pl/sql来处理,花了不少的时间。脚本虽然完成了,但是不够通用,最后发现本来几十行的pl./sql用几行shell就完成了。 比如我们修改分区的时候,语句类似下面的格式。 alter table XXXXX SPLIT PARTITION CMAXVALUE_MMAXVALUEat (2,2) INTO ( PARTITION C2_M2, PARTITION CMAXVALUE_MMAXVALUE);

比如我们的需求是这样的。如果是一个键值,分区字段就是PERIOD_KEY,会有120个分区,如果分区键值是2个,分区字段就是PERIOD_KEY,ENTITY_KEY两个组合起来。这样就是两千多个分区了。

PERIOD_KEY

0,1,2,3,4,5,6,7,8,9,10,……110,111,112,113,114,115,116,117,118,119,MAX VALUE

ENTITY_KEY

5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100

如果分区键值为1个,就可以用shell这么做。如果默认分区有一定的变化,可以作为输入参数灵活变更。 for i in {0..199} do echo 'alter table '$1' split partition '$2' at('$i') into (partition P'$i',partition '$2');' done 如果分区键值为2个,类似下面的方式。注意ENTITY_KEY是按照5n的方式来递增的。 for i in {0..199} do for ((j=5;j<=100;j=$j+5)) do echo 'alter table '$1' split partition '$2' at('$i','$j') into (partition P'$i'_C'$j',partition '$2');' done done 脚本运行后的效果如下,就完全可以脱离数据库环境来完成。 alter table XXXXX split partition PMAXVALUE at(37) into (partition P37,partition PMAXVALUE); ..... alter table XXXXX split partition PMAXVALUE_CMAXVALUE at(198,90) into (partition P198_C90,partition PMAXVALUE_CMAXVALUE); .... step7_post_par 关于分区的检查和验证,可以根据具体的业务逻辑来判断。比如我可以使用如下的方式来做一个简单验证。 这个脚本能够得到一个数据条数的列表,能够清晰的判断出来,不用全部分区的数据都查,可以根据自己的选择针对性来查就可以了。 set pages 0 set linesize 150 set feedback off select 'alter table '||table_name||' drop partition '||partition_name||' ;' from user_tab_partitions where table_name='XXXXX' and partition_name not like '%MAX%';

比如在第一步中导出的时候,有个表的数据全部分区在默认分区中。 . . exporting partition P40_C99 0 rows exported . . exporting partition PMAXVALUE_C99 1048387 rows exported Export terminated successfully without warnings. 分区之后的数据为,可以看到数据的分区就好多了。 PAR_TAB_TEST P55_C10 22161 PAR_TAB_TEST P55_C100 22224 PAR_TAB_TEST P55_C15 22215 PAR_TAB_TEST P55_C20 22370 PAR_TAB_TEST P55_C25 22207 PAR_TAB_TEST P55_C30 22422 PAR_TAB_TEST P55_C35 22374 PAR_TAB_TEST P55_C40 22501 PAR_TAB_TEST P55_C45 22225 PAR_TAB_TEST P55_C5 22349 PAR_TAB_TEST P55_C50 22391 以上是一个直观的验证,还需要再做一层验证,看看数据的分区是不是和需求一致的。这个检查至关重要。比如分区P55_C10存放的数据和键值的匹配情况。 如果粗放的检查完,不做这一层次的检查,如果出现问题,后面的步骤全都没有意义了。 SQL> select period_key,ENTITY_KEY from XXXXX partition( P55_C10) group by period_key,customer_key order by customer_key; PERIOD_KEY ENTITY_KEY ---------- ------------ 55 5 55 6 55 7 55 8 55 9 SQL> select period_key,ENTITY_KEY from XXXXXX partition( P55_C5) group by period_key,customer_key order by customer_key; PERIOD_KEY ENTITY_KEY ---------- ------------ 55 0 55 1 55 2 55 3 55 4 step8_data_append 这个部分就开始正式的数据导入了。外部表的数据迁移方式,可以参考我的文集,就不从头赘述了。http://blog.itpub.net/special/show/sid/383/ step9_stat_gather 最后就是收集统计信息了,这个部分可能会消耗一定的时间,可以先在检查后开放环境给开发来做确认,毕竟收集统计信息是可以online完成的,让他们先确认业务,后台并发跑一些session收集,可以节省较多的时间。

原文发布于微信公众号 - 杨建荣的学习笔记(jianrong-notes)

原文发表时间:2014-10-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一枝花算不算浪漫

Java应用集群下的定时任务处理方案(mysql)

5258
来自专栏杨建荣的学习笔记

MySQL中insert语句没有响应的问题分析(r11笔记第21天)

今天开发的一个同学问我一个MySQL的问题,说在测试数据库中执行一条Insert语句之后很久没有响应。我一看语句是一个很常规的insert into xxx ...

36512
来自专栏L宝宝聊IT

存储过程和触发器的应用

1574
来自专栏杨建荣的学习笔记

MySQL中批量初始化数据的对比测试(r12笔记第71天)

一直以来对于MySQL的存储过程性能还是颇有微词的,说实话够慢的。有时候想做一些对比测试,存储过程初始化几万条数据都得好一会儿,这功夫Oracle类似的测试...

3297
来自专栏数据和云

【合理授权,安全第一】聊一聊Oracle数据库的用户权限

编辑手记:年底大家最关注数据安全,之前我们说过,数据库的风险分为外部风险和内部风险。外部风险无法预估但概率较小,平时发生最多的还是内部操作的风险,因此合理控制权...

2685
来自专栏Jackson0714

【T-SQL进阶】02.理解SQL查询的底层原理

1362
来自专栏维C果糖

史上最简单的 MySQL 教程(三十五)「数据备份与还原(上)」

数据备份与还原的方式有很多种,具体可以分为:数据表备份、单表数据备份、SQL备份和增量备份。

4247
来自专栏aoho求索

MySQL探秘(三):InnoDB的内存结构和特性

 常言说得好,每个成功男人背后都有一个为他默默付出的女人,而对于MySQL来说,这个“人”就是InnoDB存储引擎。  MySQL区别于其他数据库的最为重要的特...

2701
来自专栏技术问题

MySQL探秘(三):InnoDB的内存结构和特性

常言说得好,每个成功男人背后都有一个为他默默付出的女人,而对于MySQL来说,这个“人”就是InnoDB存储引擎。  MySQL区别于其他数据库的最为重要的特点...

570
来自专栏运维技术迷

MySQL数据库(一):安装MySQL数据库

安装环境: 操作系统版本:RHEL 6.5 安装版本:MYSQL 5.1 升级版本:MYSQL 5.6 一、简述MYSQL 1.什么是数据库? DB ...

4358

扫码关注云+社区

领取腾讯云代金券