何时使用分区表
分区表是对表按照规则进行划分,这个是要根据业务场景来确定的。
建议值
1 大于2G的表
2 分区键必须反应业务需求,CUDR尽量不要跨分区操作
如果通过有效隔离,全表扫描就变成了分区扫描,降低IO,但如果已经使用索引,且结果集较小时,做分区不一定会提高效率,这点要注意。
分区表设计思路
分区的数据要尽量保持均匀,偏差控制在20%左右。分区键的选择不应经常被UPDATE,要避免NULL值出现,否则会被抛到MAXVALUE分区,还要注意键值大小写分区的问题。分区不宜过多,hash分区必须是2的n次方倍,也要考虑CPU的并发能力。
分区表类型
范围分区(Range Partition)
通常是使用频率最高的分区,如按月份划分,这样的数据保持均匀性比较好,如果划分的均匀性不是很好,需要考虑其他分区方法。
CREATE TABLE Test(
ID NUMBER,
CDATE VARCHAR2(8)
)
PARTITION BY RANGE(CDATE)(
PARTITION par_test_2017_q1 VALUES LESS THAN ('20170401'),
PARTITION par_test_2017_q2 VALUES LESS THAN ('20170701'),
PARTITION par_test_2017_q3 VALUES LESS THAN ('201701001'),
PARTITION par_test_2017_q3 VALUES LESS THAN ('20180101'),
PARTITION par_test_2018 VALUES LESS THAN (maxvalue),
)ENABLE ROW MOVEMENT;
--ENABLE ROW MOVEMENT要加,因为分区键如果需要UPDATE操作的话,会对其进行重新分区,有可能分到别的去了。
哈希分区(Hash Partition)
如果数据不是那么容易进行划分,通过这种方式就很灵活了。可以将数据均匀的插入到不同的块,在并发时有利于提高效率,当无法用Range分区时,就可以用Hash分区。
CREATE TABLE Test(
ID NUMBER,
CDATE VARCHAR2(8)
)
PARTITION BY HASH(NAME)(
PARTITION par_test_01,
PARTITION par_test_02,
PARTITION par_test_03,
PARTITION par_test_04
);
列表分区(List Partition)
当需要明确控制如何将数据进行分区时,采用这种方式。只能进行单列分区,可以讲数据进行分组,比如按城市分区,几个城市放一起。
CREATE TABLE Test(
ID NUMBER,
CITY VARCHAR2(8)
)
PARTITION BY LIST(CITY) (
PARTITION par_test_01 VALUES('BJ','BD'),
PARTITION par_test_02 VALUES('XA','SJZ'),
PARTITION par_test_03 VALUES('SH','HZ'),
PARTITION par_test_01 VALUES('SZ','GZ')
)ENABLE ROW MOVEMENT;
复合分区
侧重于数据归档了,将上述三个组合起来用。根据业务需求的数据分布来了选择合适的组合。
语法
PARTITION BY RANGE(CDATE) SUBPARTITION BY HASH(NAME)(
PARTITION par_test_2017_q1 VALUES LESS THAN ('20170401')(
SUBPARTITION sp_test_2017_q1_01,
SUBPARTITION sp_test_2017_q1_02,
SUBPARTITION sp_test_2017_q1_03,
SUBPARTITION sp_test_2017_q1_04),
PARTITION par_test_2017_q1 VALUES LESS THAN (maxvalue)(
SUBPARTITION sp_test_2017_max_01,
SUBPARTITION sp_test_2017_max_02,
SUBPARTITION sp_test_2017_max_03,
SUBPARTITION sp_test_2017_max_04),
)
除了以上三种分区,Oracle还提供了4个分区方式,来针对不同的使用场景。我感觉可以作为上述三种主流分区的补充。
间隔分区(Interval Partition)
你有没有想过使用范围分区,随着时间的增长,你会不停的手动增加新的分区。间隔分区就是解决这种业务场景,当满足条件后,会自动增加分区。
PARTITION BY RANGE(CDATE) INERVAL (NUMTOYMINTERVAL(1,'mouth'))(
PARTITION par_test_2017_q1 VALUES LESS THAN (TO_DATE('20170401','yyyymmdd'))
)ENABLE ROW MOVEMENT;
格式:NumToYMInterval(n, interval_unit);
n: 数值类型
interval_unit: ‘YEAR’, ‘MONTH’ ,或其他可以转换成这两个值之一的表达式
NumToYMInterval(1, ‘YEAR’) :一年后的间隔
NumToYMInterval(-1, ‘MONTH’): 一个月前
系统分区(System Partition)
系统分区不指定分区条件,而是在SQL里指定插入哪个分区。
PARTITION BY SYSTEM(
PARTITION par_test_01,
PARTITION par_test_02
)
虚拟列分区
这种虚拟列数据不实际存在磁盘中,而是在SQL计算时实时得到,虚拟列可以和普通列一样,建索引、做分区键,收集信息。
CREATE TABLE test(
ID NUMBER,
BUY NUMBER,
SELL NUMBER,
GAIN NUMBER AS (SELL-BUY)
)
PARTITION BY RANGE(GAIN)(
PARTITION par_test_01 VALUES LESS THAN (10000),
PARTITION par_test_02 VALUES LESS THAN (20000),
PARTITION par_test_max VALUES LESS THAN (maxvalue)
)
关联分区(Reference Partition)
主表分区、子表分区。主表变了以后,子表会自动适应。这个以后在讨论,感觉目前用的不多。知道这个概念即可。