您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

Oracle 11g新特性:更加灵活的分区策略

2026/3/17 5:51:27发布8次查看
欢迎进入oracle社区论坛,与200万技术人员互动交流 >>进入 前不久,曾经接手一个性能调优案例:这是一个报表系统,其基础数据主要存储于三张表中。表的大小已经很大了,最大一张接近100g。在生成报表时需要长时间才能返回结果,一些online查询甚至经常timeou
欢迎进入oracle社区论坛,与200万技术人员互动交流 >>进入
    前不久,曾经接手一个性能调优案例:这是一个报表系统,其基础数据主要存储于三张表中。表的大小已经很大了,最大一张接近100g。在生成报表时需要长时间才能返回结果,一些online查询甚至经常timeout。表中存储的是2万多个公司的数据,报表的生成也是以公司为单位的,因此,这一调优方案的思路比较明确:将表按公司分区。但是,这中间却存在一些麻烦:每个公司的数据并不是均衡的。其中近200家公司属于vip用户,他们的数据量最大,每个公司差不多是十几万到几十万的数据量,其总量占了全部数据的30%左右;而其它非vip用户的数据基本上每个都在1万以内。而我们的主要目标就是要优先保证vip用户获取到最佳的性能(由于其数据量,当前最大的性能问题恰恰就出在这些vip用户上)。因此,我们提出了2中分区方案:
    基于company id的hash分区;
    基于company id的list分区;
    但是,这两种方案各有优缺点:
    对于hash分区,分区的大小更加均衡,因而性能也更加均衡。但是,可能出现一些无法控制的极端现象:hash分区仅仅是对company id使用hash函数进行分组,它能做到每个分区分配基本相当数量的company id,但是每个company id对应的数据量并不考虑在内,因此可能出现某些分区集中的都是vip数据或者都是非vip数据,造成分区过大或过小;另外一个缺点就是我们很难直接干预某个公司的性能。例如,可能有某个非vip用户成为了vip用户,其数据量激增,它又正好处于一个大的分区上,这时,我们很难将其从这个分区剥离出来,除非它所在分区正好出在一个即将分裂的分区上。
    对于list分区,vip用户的性能能够得到保证。我们可以将每个vip用户单独存储在一个分区上,但是,不可能将非vip用户单独存储开(不仅增加维护难度,且增加整个表的大小),只能将非vip用户存储在几个分区上。但是这样还是造成ddl语句非常复杂,并且非vip的分区很大(每个都在10g左右,而vip分区最大才200m)。
    由于list分区更加接近我们的优化目的,最终还是采用了list分区。
    其实,期间我们曾经考虑过使用复合分区。在10g中(我们的生产库是10g),仅支持2种复合分区:range-list和range-hash。我们的解决方案是:为表增加一个数字类型的id字段,vip用户对应的数字大于100,000,非vip用户的id小于100,000。每个vip用户被单独放置在一个range分区中,所有非vip用户被放置在一个range分区中,然后再对非vip分区通过hash划分子分区。这样,即能保证vip用户的性能,也能均衡非vip用户的性能。但是,由于这种方案需要增加一个非业务的字段,以及其它一些原因,最终被否决了。
    到11g中,oracle的分区策略更加灵活了。首先,11g支持更多方式的组合分区,除10g支持的两种之外,还支持range-range、list-range、list-list、list-hash的组合分区策略。对于我们上述这个案例,就可以通过list-hash的组合分区来解决。以下就是一个list-hash分区的演示:
    sql代码
    sql> create table par_test
    2 partition by list (owner)
    3 subpartition by hash (owner)
    4 store in (example)
    5 (partition p1 values ('sys'), 6 partition p2 values ('public'),
    7 partition def values (default)
    8 subpartitions 4
    9 )
    10 as select * from dba_objects
    11 /
    table created.
    sql> analyze table par_test compute statistics;
    table analyzed. sql> select partition_name, subpartition_name, num_rows, blocks from dba_tab_subpartitions
    2 where table_name = 'par_test';
    partition_name subpartition_name num_rows blocks
  ------------------------------ ------------------------------ ---------- ----------
    p2 sys_subp154 26604 434
    def sys_subp158 4529 70
    def sys_subp157 2783 45
    def sys_subp156 2422 39
    def sys_subp155 2854 47
    p1 sys_subp153 29770 437
    6 rows selected.
    顺便再提一下11g新增的其他分区策略。
    针对range partition,11g有了一种更加灵活的方式:interval partition。例如,我们一些分区表是依赖于时间做的范围分区:每个月的数据存放到一个分区中。随着数据的增长,还需要有一个作业来增加新的分区以满足上述策略。而在11g中,通过interval parition,就无需这中人为的维护作业了,oracle会为新的数据自动增加分区:
    sql代码
    sql> create table par_test2 (a number, b date)
    2 partition by range (b)
    3 interval (numtoyminterval(1,'month'))
    4 store in (example)
    5 (
    6 partition values less than (to_date('2009-09-01','yyyy-mm-dd'))
    7 )
    8 ;
    table created. sql> insert into par_test2 values(1, sysdate); 1 row created.
    sql> commit;
    commit complete. sql> select partition_name, high_value from dba_tab_partitions
    2 where table_name = 'par_test2';
    partition_name high_value
  ------------------------------ --------------------------------------------------------------------------------
    sys_p164 to_date(' 2009-09-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss', 'nls_calendar=gregoria ' sql> insert into par_test2 values(1, to_date('2009-10-01','yyyy-mm-dd')); 1 row created.
    sql> commit;
    commit complete. sql> select partition_name, high_value from dba_tab_partitions
    2 where table_name = 'par_test2';
    partition_name high_value
[1] [2]
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product