在大型的企业应用或企业级的数据库应用中,要处理的数据量通常可以达到几十到几百GB,有的甚至可以到TB级。虽然存储介质和数据处理技术的发展也很快,但是仍然不能满足用户的需求,为了使用户的大量的数据在读写操作和查询中速度更快,Oracle提供了对表和索引进行分区的技术,以改善大型应用系统的性能。
使用分区的优点:
·增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用;
·维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可;
·均衡I/O:可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能;
·改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。
Rnage分区 => 基于分区键值的范围将数据映射到所建立的分区上。
例如,将销售数据区分到月。
CREATE TABLE sales_range
(
salesman_id NUMBER(5),
salesman_name VARCHAR2(30),
sales_amount NUMBER(10),
sales_date DATE
)
PARTITION BY RANGE(sales_date)
(
PARTITION sales_jan2010 VALUES LESS THAN(TO_DATE('01/02/2010','DD/MM/YYYY')),
PARTITION sales_feb2010 VALUES LESS THAN(TO_DATE('01/03/2010','DD/MM/YYYY')),
PARTITION sales_mar2010 VALUES LESS THAN(TO_DATE('01/04/2010','DD/MM/YYYY'))
);
Interval分区 => 前面介绍的Range分区需要手动添加和控制分区段,设置Interval段可以解决这个问题
CREATE TABLE sales
(
item# INTEGER,
quantity INTEGER,
store_name VARCHAR(30),
state_code VARCHAR(2),
sale_date DATE
)
PARTITION BY RANGE(sal_date)
INTERVAL(NUMTOYMINTERVAL(1,'MONTH'))
(
PARTITION olddate VALUES LESS THAN (TO_DATE('01-JAN-2008','DD-MON-YYYY'))
);
List分区 => 可以控制如何将行映射到分区中。可以为每个分区的键上定义离散的值。
例如,下例使用低于地域对销售数据分区。
CREATE TABLE sales_list
(
salesman_id NUMBER(5),
salesman_name VARCHAR2(30),
sales_state VARCHAR2(20),
sales_amount NUMBER(10),
sales_date DATE
)
PARTITION BY LIST(sales_state)
(
PARTITION sales_west VALUES ('XiZang','SiChuan') COMPRESS,
PARTITION sales_east VALUES ('FuJian','XiaMen'),
PARTITION sales_central VALUES ('HuNan')
);
Hash分区 => 散列分区为通过指定分区编号来均匀分布数据的一种分区类型,因为通过在I/O设备上进行散列分区,使得这些分区大小一致。
CREATE TABLE sales_hash
(
salesman_id NUMBER(5),
salesman_name VARCHAR2(30),
sales_amount NUMBER(10),
week_no NUMBER(2)
)
PARTITION BY HASH(salesman_id)
(
PARTITION sale1,
PARTITION sale2,
PARTITION sale3,
PARTITION sale4
);
合成分区 => 当表很大,分区可能很多或者过大难于管理时,合成分区可以将分区按其他的准则进一步划分。
例如:将销售表先按月份划分,然后再按地区进行划分。
CREATE TABLE sales
(
SalesID NUMBER(5),
Quantity NUMBER(5),
ProvinceID NUMBER(2),
Sale_Date DATE
)
PARTITION BY RANGE (sale_date)
INTERVAL(NUMTOYMINTERVAL(1,'MONTH'))
SUBPARTITION BY list(ProvinceID)
(
PARTITION olddate VALUES LESS THAN(TODATE('01-JAN-2008','DD-MON-YYYY'))
(
SUBPARTITION BeiJing VALUES(1),
SUBPARTITION ShangHai VALUES(2),
SUBPARTITION GuangZhou VALUES(3),
)
)
引用分区 => 对外键引用表和主表进行相同方式的分区。
例如:有Order 和 OrderDetail两个表,对Order表进行按时间的Range分区,同时对OrderDetail也采用同Order相同方式的Range分区,即使OrderDetail没有OrderDate。
CREATE TABLE Orders
(
OrderID NUMBER(5),
CustID NUMBER(3),
OrderDate DATE,
ShipDate DATE,
CONSTRAINT Orders_PK PRIMARY KEY(OrderID),
CONSTRAINT Orders_FK_Cust FOREIGN KEY (CustID) REFERENCES Customers
)
PARTITION BY RANGE (OrderDate)
INTERVAL(NUMTOYMINTERVAL(1,'MONTH'))
(
PARTITION olddate VALUES LESS THAN (TO_DATE('01-JAN-2008','DD-MON-YYYY'))
);
CREATE TABLE OrderDetail
(
OrderDetailID NUMBER(5),
OrderID NUMBER(5) NOT NULL,
StockID NUMBER(5),
Quantity NUMBER(6,2) NOT NULL,
DIscount NUMBER(4,2),
CONSTRAINT OrderDetail_PK PRIMARY KEY(OrderDetailID),
CONSTRAINT OrderDetail_FK_Stock FOREIGN KEY(StockID) REFERENCES Stock,
CONSTRAINT OrderDetail_FK_Order FOREIGN KEY(OrderID) REFERENCES Order,
)
PARTITION BY REFERENCE(OrderDetail_FK_Order)
分区的局部索引和全局索引
建立了分区后,我们可以为分区建立索引。
局部索引 => 查询仅限定于某个分区内部。
全局索引 => 查询在各个分区间进行查询。
CREATE INDEX Sale_IDX ON Sales (Sale_Date) LOCAL;
CREATE INDEX Sale_IDX ON Sales (Sale_Date) LOCAL
(
PARTITION sale1,
PARTITION sale2,
PARTITION sale3 ,
PARTITION sale4
);