有时仅有范围、散列或列表模式的分区是不够的。你可以将大表进一步分解成多个子分区,以便更好地控制数据位置和性能。Oracle提供了几类组合分区。例如,在范围-散列分区方法下,首先用范围分区对表进行分区,然后用散列方法对每个分区进行子分区。在范围-列表分区的方案中,首先使用范围分区对表进行分区,然后使用列表分区对这些分区进行子分区。类似,可以使用范围-范围、列表-列表、列表-散列和列表-范围等的组合分区。
1.范围-散列分区
有时如果只按范围对表进行分区,数据分布可能会并不十分均匀。那么,在范围分区之后再进行散列分区是一个更好的分区模式。尽管这样做使管理更为复杂,但是它能更有效地存储数据。
范围-散列分区结合了范围和散列分区模式的优点。范围分区易于实现,而散列分区则提供了条带化和并行性这样的优势。
创建范围-散列分区表
CREATE TABLE scoutgear
(
equipno NUMBER,
equipname VARCHAR(32),
price NUMBER
)
PARTITION BY RANGE(equipno)
SUBPARTITION BY HASH(equipname)
SUBPARTITIONS 8 STORE IN (tsl, ts2, tS3, ts4)
(
PARTITION pl VALUES LESS THAN (1000),
PARTITION p2 VALUES LESS THAN (2000),
PARTITION p3 VALUES LESS THAN (3000),
PARTITION p4 VALUES LESS THAN (MAXVALUE)
);
在该例中,scoutgear表首先基于equipno列进行范围分区一即创建4个基于范围的分区。然后使用散列分区模式将奁4个分区根据equipname列进行再分区,一共得到32个子分区。请注意第3行中的SUBPARTITIONS子句。
2.范围-列表分区
在范围-列表分区方法中,首先要根据范围值进行数据分区。然后使用列表分区方法用一列离散值将第一组分区进行分解。
创建范围-列表分区表
CREATE TABLE quarterly_regional_sales
(
ticket_no NUMBER,
sale_year INT NOT NULL,
sale_month INT NOT NULL,
sale_day DATE,
destination_city CHAR(3),
start_city CHAR(3)
)
PARTITION BY RANGE(sale_day)
SUBPARTITION BY LIST (start_city)
(
PARTITION q1_2004 VALUES LESS THAN (TO_DATE('1-APR-2004','DD-MON-YYYY')) TABLESPACE t1
(
subpartition q12004_northeast_salse values ('NYC','BOS','PEN'),
subpartition q12004_southwest_salse values ('DFW','ORL','HOW'),
subpartition q12004_pacificwest_salse values ('SAN','LOS','WAS'),
subpartition q12004_southeast_salse values ('MIA','CHA','ATL')
),
PARTITION q2_2004 VALUES LESS THAN (TO_DATE('1-JUL-2004','DD-MON-YYYY')) TABLESPACE t2
(
subpartition q22004_northeast_salse values ('NYC','BOS','PEN'),
subpartition q22004_southwest_salse values ('DFW','ORL','HOW'),
subpartition q22004_pacificwest_salse values ('SAN','LOS','WAS'),
subpartition q22004_southeast_salse values ('MIA','CHA','ATL')
),
PARTITION q3_2004 VALUES LESS THAN (TO_DATE('1-OCT-2004','DD-MON-YYYY')) TABLESPACE t3
(
subpartition q32004_northeast_salse values ('NYC','BOS','PEN'),
subpartition q32004_southwest_salse values ('DFW','ORL','HOW'),
subpartition q32004_pacificwest_salse values ('SAN','LOS','WAS'),
subpartition q32004_southeast_salse values ('MIA','CHA','ATL')
),
PARTITION q4_2004 VALUES LESS THAN (TO_DATE('1-JAN-2005','DD-MON-YYYY')) TABLESPACE t4
(
subpartition q42004_northeast_salse values ('NYC','BOS','PEN'),
subpartition q42004_southwest_salse values ('DFW','ORL','HOW'),
subpartition q42004_pacificwest_salse values ('SAN','LOS','WAS'),
subpartition q42004_southeast_salse values ('MIA','CHA','ATL')
)
);
上面的语句将在范围-列表分区表中创建16个子分区,每个表空间4个子分区,分别为tl、t2、t3、t4.每当将一行数据插入到quarterly_regional_sale表时,Oracle首先检査该行的分区列值是否落在指定的分区范围内。然后Oracle通过基于子分区点列表值把子分区的列值映射到相应的子分区上,再将该行映射到该分区的一个子分区中。例如,列值为(9999,2004,10,1,'DAL','HOU')的行被映射到子分区q42004_southwest_sales上。
3.组合间隔-列表分区的表
你必须用子分区模板创建一个具有列表子分区的表。否则,对每个间隔分区将只能创建一个默认的子分区。
sales表首先在time_id列上进行间隔分区,以天为间隔。然后按channel_id列上的列表进行子分区。
创建间隔-列表分区表
CREATE TABLE sales
(
prod_id NUMBER(6),
cust_id NUMBER,
time_id date,
channel_id char(1),
promo_id NUMBER(6),
quantity_sold NUMBER(3),
amount_sold NUMBER(10,2)
)
PARTITION BY RANGE (time_id)
INTERVAL (NUMTODSINTERVAL(1,'DAY'))
SUBPARTITION BY LIST(channel_id)
SUBPARTITION TEMPLATE
(
SUBPARTITION p_catalog VALUES ('C'),
SUBPARTITION p_internet VALUES ('I'),
SUBPARTITION p_partners VALUES ('P'),
SUBPARTITION p_direct_sales VALUES ('S'),
SUBPARTITION p_tele_sales VALUES ('T')
)
(
PARTITION before_2000 VALUES LESS THAN (TO DATE('01-JAN-2000','dd-MON-yyyy1))
)
PARALLEL;
4.组合间隔-范围分区
与列表子分区情况一样,如果你想在间隔-范围分区表中对未来的间隔分区创建范围子分区,则必须使用子分区模板。没有这样的模板,将只能用每个间隔分区的MAXVALUE上界创建一个范围子分区。
创建一个间隔-范围组合的分区表。间隔分区用time_id列上的日期间隔创建,范围子分区在amount_sold列上分区。
CREATE TABLE sales
(
prod_id NUMBER(6),
cust_id NUMBER,
time_id date,
channel_id char(1),
promo_id NUMBER(6),
quantity_sold NUMBER(3),
amount_sold NUMBER(10,2)
)
PARTITION BY RANGE (time_id)
INTERVAL (NUMTODSINTERVAL(1,'DAY'))
SUBPARTITION BY RANGE(amount_sold)
SUBPARTITION TEMPLATE
(
SUBPARTITION p_low VALUES LESS THAN (1000),
SUBPARTITION p_medium VALUES LESS THAN (4000),
SUBPARTITION p_high VALUES LESS THAN (8000),
SUBPARTITION p_ultimate VALUES LESS THAN (maxvalue)
)
(
PARTITION before_2000 VALUES LESS THAN (TO DATE('01-JAN-2000','dd-MON-yyyy1))
)
PARALLEL;




