- 浏览: 121015 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
liguocai2009:
liguocai2009 写道经过我我的测试,600万的数据, ...
Oracle row_number() over()解析函数高效实现分页 -
liguocai2009:
经过我我的测试,600万的数据,row_number()耗时4 ...
Oracle row_number() over()解析函数高效实现分页 -
学会做人:
lbs1988 写道扯淡 谁说row_number() ove ...
Oracle row_number() over()解析函数高效实现分页 -
lbs1988:
扯淡 谁说row_number() over 效率高 他们效率 ...
Oracle row_number() over()解析函数高效实现分页 -
id0096:
没觉得效率高到哪里去...用180W条数据测试,很多情况下没有 ...
Oracle row_number() over()解析函数高效实现分页
在ORACLE里如果遇到特别大的表,可以使用分区的表来改变其应用程序的性能。
1.1 分区表PARTITION table
在ORACLE里如果遇到特别大的表,可以使用分区的表来改变其应用程序的性能。
1.1.1 分区表的建立:
某公司的每年产生巨大的销售记录,DBA向公司建议每季度的数据放在一个分区内,以下示范的是该公司1999年的数据(假设每月产生30M的数据),操作如下:
范围分区表:
CREATE TABLE sales
(invoice_no NUMBER,
...
sale_date DATE NOT NULL )
PARTITION BY RANGE (sale_date)
(PARTITION sales1999_q1
VALUES LESS THAN (TO_DATE(‘1999-04-01’,’YYYY-MM-DD’)
TABLESPACE ts_sale1999q1,
PARTITION sales1999_q2
VALUES LESS THAN (TO_DATE(‘1999-07-01’,’YYYY-MM-DD’)
TABLESPACE ts_sale1999q2,
PARTITION sales1999_q3
VALUES LESS THAN (TO_DATE(‘1999-10-01’,’YYYY-MM-DD’)
TABLESPACE ts_sale1999q3,
PARTITION sales1999_q4
VALUES LESS THAN (TO_DATE(‘2000-01-01’,’YYYY-MM-DD’)
TABLESPACE ts_sale1999q4 );
--values less than (maxvalue)
列表分区表:
create table emp (
empno number(4),
ename varchar2(30),
location varchar2(30))
partition by list (location)
(partition p1 values ('北京'),
partition p2 values ('上海','天津','重庆'),
partition p3 values ('广东','福建')
partition p0 values (default)
);
哈希分区:
create table emp (
empno number(4),
ename varchar2(30),
sal number)
partition by hash (empno)
partitions 8
store in (emp1,emp2,emp3,emp4,emp5,emp6,emp7,emp8);
组合分区:
范围哈希组合分区:
create table emp (
empno number(4),
ename varchar2(30),
hiredate date)
partition by range (hiredate)
subpartition by hash (empno)
subpartitions 2
(partition e1 values less than (to_date('20020501','YYYYMMDD')),
partition e2 values less than (to_date('20021001','YYYYMMDD')),
partition e3 values less than (maxvalue));
范围列表组合分区:
CREATE TABLE customers_part (
customer_id NUMBER(6),
cust_first_name VARCHAR2(20),
cust_last_name VARCHAR2(20),
nls_territory VARCHAR2(30),
credit_limit NUMBER(9,2))
PARTITION BY RANGE (credit_limit)
SUBPARTITION BY LIST (nls_territory)
SUBPARTITION TEMPLATE
(SUBPARTITION east VALUES ('CHINA', 'JAPAN', 'INDIA', 'THAILAND'),
SUBPARTITION west VALUES ('AMERICA', 'GERMANY', 'ITALY', 'SWITZERLAND'),
SUBPARTITION other VALUES (DEFAULT))
(PARTITION p1 VALUES LESS THAN (1000),
PARTITION p2 VALUES LESS THAN (2500),
PARTITION p3 VALUES LESS THAN (MAXVALUE));
create table t1 (id1 number,id2 number)
partition by range (id1) subpartition by list (id2)
(partition p11 values less than (11)
(subpartition subp1 values (1))
);
索引分区:
CREATE INDEX month_ix ON sales(sales_month)
GLOBAL PARTITION BY RANGE(sales_month)
(PARTITION pm1_ix VALUES LESS THAN (2)
PARTITION pm12_ix VALUES LESS THAN (MAXVALUE));
1.1.2 分区表的维护:
增加分区:
ALTER TABLE sales ADD PARTITION sales2000_q1
VALUES LESS THAN (TO_DATE(‘2000-04-01’,’YYYY-MM-DD’)
TABLESPACE ts_sale2000q1;
如果已有maxvalue分区,不能增加分区,可以采取分裂分区的办法增加分区!
删除分区:
ALTER TABLE sales DROP PARTION sales1999_q1;
截短分区:
alter table sales truncate partiton sales1999_q2;
合并分区:
alter table sales merge partitons sales1999_q2, sales1999_q3 into sales1999_q23;
alter index ind_t2 rebuild partition p123 parallel 2;
分裂分区:
ALTER TABLE sales
SPLIT PARTITON sales1999_q4
AT TO_DATE (‘1999-11-01’,’YYYY-MM-DD’)
INTO (partition sales1999_q4_p1, partition sales1999_q4_p2) ;
alter table t2 split partition p123 values (1,2) into (partition p12,partition p3);
交换分区:
alter table x exchange partition p0 with table bsvcbusrundatald ;
访问指定分区:
select * from sales partition(sales1999_q2)
EXPORT指定分区:
exp sales/sales_password tables=sales:sales1999_q1
file=sales1999_q1.dmp
IMPORT指定分区:
imp sales/sales_password FILE =sales1999_q1.dmp
TABLES = (sales:sales1999_q1) IGNORE=y
查看分区信息:
user_tab_partitions, user_segments
注:若分区表跨不同表空间,做导出、导入时目标数据库必须预建这些表空间。分表区各区所在表空间在做导入时目标数据库一定要预建这些表空间!这些表空间不一定是用户的默认表空间,只要存在即可。如果有一个不存在,就会报错!
默认时,对分区表的许多表维护操作会使全局索引不可用,标记成UNUSABLE。 那么就必须重建整个全局索引或其全部分区。如果已被分区,Oracle 允许在用于维护操作的ALTER TABLE 语句中指定UPDATE GLOBAL INDEXES 来重载这个默认特性,指定这个子句也就告诉Oracle 当它执行维护操作的DDL 语句时更新全局索引,这提供了如下好处:
1.在操作基础表的同时更新全局索引这就不需要后来单独地重建全局索引;
2.因为没有被标记成UNUSABLE, 所以全局索引的可用性更高了,甚至正在执行分区的DDL 语句时仍然可用索引来访问表中的其他分区,避免了查询所有失效的全局索引的名字以便重建它们;
另外在指定UPDATE GLOBAL INDEXES 之前还要考虑如下性能因素:
1.因为要更新事先被标记成UNUSABLE 的索引,所以分区的DDL 语句要执行更长时间,当然这要与先不更新索引而执行DDL 然后再重建索引所花的时间做个比较,一个适用的规则是如果分区的大小小于表的大小的5% ,则更新索引更快一点;
2.DROP TRUNCATE 和EXCHANGE 操作也不那么快了,同样这必须与先执行DDL 然后再重建所有全局索引所花的时间做个比较;
3.要登记对索引的更新并产生重做记录和撤消记录,重建整个索引时可选择NOLOGGING;
4.重建整个索引产生一个更有效的索引,因为这更利于使用空间,再者重建索引时允许修改存储选项。
注意分区索引结构表不支持UPDATE GLOBAL INDEXES 子句。
1.1.3 普通表变为分区表
将已存在数据的普通表转变为分区表,没有办法通过修改属性的方式直接转化为分区表,必须通过重建的方式进行转变,一般可以有三种方法,视不同场景使用:
用例:
方法一:利用原表重建分区表。
CREATE TABLE T (ID NUMBER PRIMARY KEY, TIME DATE);
INSERT INTO T
SELECT ROWNUM, SYSDATE - ROWNUM FROM DBA_OBJECTS WHERE ROWNUM <= 5000;
COMMIT;
CREATE TABLE T_NEW (ID, TIME) PARTITION BY RANGE (TIME)
(PARTITION P1 VALUES LESS THAN (TO_DATE('2000-1-1', 'YYYY-MM-DD')),
PARTITION P2 VALUES LESS THAN (TO_DATE('2002-1-1', 'YYYY-MM-DD')),
PARTITION P3 VALUES LESS THAN (TO_DATE('2005-1-1', 'YYYY-MM-DD')),
PARTITION P4 VALUES LESS THAN (MAXVALUE))
AS SELECT ID, TIME FROM T;
RENAME T TO T_OLD;
RENAME T_NEW TO T;
SELECT COUNT(*) FROM T;
COUNT(*)
----------
5000
SELECT COUNT(*) FROM T PARTITION (P1);
COUNT(*)
----------
2946
SELECT COUNT(*) FROM T PARTITION (P2);
COUNT(*)
----------
731
SELECT COUNT(*) FROM T PARTITION (P3);
COUNT(*)
----------
1096
优点:方法简单易用,由于采用DDL语句,不会产生UNDO,且只产生少量REDO,效率相对较高,而且建表完成后数据已经在分布到各个分区中了。
不足:对于数据的一致性方面还需要额外的考虑。由于几乎没有办法通过手工锁定T表的方式保证一致性,在执行CREATE TABLE语句和RENAME T_NEW TO T语句直接的修改可能会丢失,如果要保证一致性,需要在执行完语句后对数据进行检查,而这个代价是比较大的。另外在执行两个RENAME语句之间执行的对T的访问会失败。
适用于修改不频繁的表,在闲时进行操作,表的数据量不宜太大。
方法二:使用交换分区的方法。
Drop table t;
CREATE TABLE T (ID NUMBER PRIMARY KEY, TIME DATE);
INSERT INTO T
SELECT ROWNUM, SYSDATE - ROWNUM FROM DBA_OBJECTS WHERE ROWNUM <= 5000;
COMMIT;
CREATE TABLE T_NEW (ID NUMBER PRIMARY KEY, TIME DATE) PARTITION BY RANGE (TIME)
(PARTITION P1 VALUES LESS THAN (TO_DATE('2005-9-1', 'YYYY-MM-DD')),
PARTITION P2 VALUES LESS THAN (MAXVALUE));
ALTER TABLE T_NEW EXCHANGE PARTITION P1 WITH TABLE T;
RENAME T TO T_OLD;
RENAME T_NEW TO T;
优点:只是对数据字典中分区和表的定义进行了修改,没有数据的修改或复制,效率最高。如果对数据在分区中的分布没有进一步要求的话,实现比较简单。在执行完RENAME操作后,可以检查T_OLD中是否存在数据,如果存在的话,直接将这些数据插入到T中,可以保证对T插入的操作不会丢失。
不足:仍然存在一致性问题,交换分区之后RENAME T_NEW TO T之前,查询、更新和删除会出现错误或访问不到数据。如果要求数据分布到多个分区中,则需要进行分区的SPLIT操作,会增加操作的复杂度,效率也会降低。
适用于包含大数据量的表转到分区表中的一个分区的操作。应尽量在闲时进行操作。
方法三:Oracle9i以上版本,利用在线重定义功能
Drop table t;
CREATE TABLE T (ID NUMBER PRIMARY KEY, TIME DATE);
INSERT INTO T
SELECT ROWNUM, SYSDATE - ROWNUM FROM DBA_OBJECTS WHERE ROWNUM <= 5000;
COMMIT;
EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE(USER, 'T');
PL/SQL 过程已成功完成。
CREATE TABLE T_NEW (ID NUMBER PRIMARY KEY, TIME DATE) PARTITION BY RANGE (TIME)
(PARTITION P1 VALUES LESS THAN (TO_DATE('2004-7-1', 'YYYY-MM-DD')),
PARTITION P2 VALUES LESS THAN (TO_DATE('2005-1-1', 'YYYY-MM-DD')),
PARTITION P3 VALUES LESS THAN (TO_DATE('2005-7-1', 'YYYY-MM-DD')),
PARTITION P4 VALUES LESS THAN (MAXVALUE));
表已创建。
EXEC DBMS_REDEFINITION.START_REDEF_TABLE(USER, 'T', 'T_NEW');
PL/SQL 过程已成功完成。
EXEC DBMS_REDEFINITION.FINISH_REDEF_TABLE(USER, 'T', 'T_NEW');
PL/SQL 过程已成功完成。
SELECT COUNT(*) FROM T;
COUNT(*)
----------
5000
SELECT COUNT(*) FROM T PARTITION (P3);
COUNT(*)
----------
1096
优点:保证数据的一致性,在大部分时间内,表T都可以正常进行DML操作。只在切换的瞬间锁表,具有很高的可用性。这种方法具有很强的灵活性,对各种不同的需要都能满足。而且,可以在切换前进行相应的授权并建立各种约束,可以做到切换完成后不再需要任何额外的管理操作。
不足:实现上比上面两种略显复杂。
适用于各种情况。
==============================================================================================================================================================
==============================================================================
这里只给出了在线重定义表的一个最简单的例子,详细的描述和例子可以参考下面两篇文章。
举个在线重定义使用的例子:
SQL> create table test_primary (id number primary key);
表已创建。
SQL> insert into test_primary select rownum from dba_objects;
已创建6264行。
SQL> commit;
提交完成。
SQL> create table orgin_table (id number, fid number, name varchar2(30), create_date date)
2 tablespace users;
表已创建。
SQL> insert into orgin_table select rownum, rownum, object_name, created from dba_objects
2 where owner = 'SYS';
已创建4034行。
SQL> commit;
提交完成。
SQL> alter table orgin_table add constraint pk_orgin_table primary key (id);
表已更改。
SQL> create or replace trigger tr_orgin_table
2 before insert on orgin_table for each row
3 begin
4 null;
5 end;
6 /
触发器已创建
SQL> create index ind_orgin_table_create_date on orgin_table(create_date);
索引已创建。
SQL> alter table orgin_table add constraint f_orgin_primary_id foreign key (fid)
2 references test_primary (id);
表已更改。
SQL> begin
2 dbms_redefinition.can_redef_table('yangtk', 'orgin_table', dbms_redefinition.cons_use_pk);
3 end;
4 /
PL/SQL 过程已成功完成。
SQL> create table inter_table
2 (id number, fid number, new_name varchar2(30), create_date date, comments varchar2(1000))
3 tablespace yangtk
4 partition by range (create_date)
5 (partition p1 values less than (to_date('2005-1-1', 'yyyy-mm-dd')),
6 partition p2 values less than (maxvalue));
表已创建。
SQL> alter table inter_table add constraint pk_inter_table primary key (id);
表已更改。
SQL> begin
2 dbms_redefinition.start_redef_table('yangtk', 'orgin_table', 'inter_table',
3 'ID ID, FID FID, NAME NEW_NAME, CREATE_DATE CREATE_DATE, ''NO COMMENTS'' COMMENTS',
4 DBMS_REDEFINITION.CONS_USE_PK);
5 END;
6 /
PL/SQL 过程已成功完成。
SQL> SELECT COUNT(*) FROM INTER_TABLE;
COUNT(*)
----------
4034
SQL> COL COMMENTS FORMAT A20
SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
会话已更改。
SQL> SELECT * FROM INTER_TABLE WHERE ID = 1;
ID FID NEW_NAME CREATE_DATE COMMENTS
---------- ---------- ------------ ------------------- --------------------
1 1 ACCESS$ 2004-10-18 16:14:23 NO COMMENTS
SQL> INSERT INTO ORGIN_TABLE
2 SELECT 4034+ROWNUM, 4034+ROWNUM, OBJECT_NAME, CREATED FROM DBA_OBJECTS
3 WHERE OWNER = 'SYSTEM';
已创建404行。
SQL> COMMIT;
提交完成。
SQL> begin
2 dbms_redefinition.sync_interim_table('yangtk', 'orgin_table', 'inter_table');
3 end;
4 /
PL/SQL 过程已成功完成。
SQL> select count(*) from INTER_TABLE;
COUNT(*)
----------
4438
SQL> alter table inter_table add constraint fk_inter_primary_id foreign key (fid)
2 references test_primary (id) disable;
表已更改。
SQL> create index ind_inter_table_date on inter_table(create_date);
索引已创建。
SQL> create index ind_inter_table_fid on inter_table(fid);
索引已创建。
SQL> create or replace trigger tr_inter_table
2 before insert on inter_table for each row
3 begin
4 null;
5 end;
6 /
触发器已创建
SQL> begin
2 dbms_redefinition.finish_redef_table('yangtk', 'orgin_table', 'inter_table');
3 end;
4 /
PL/SQL 过程已成功完成。
SQL> desc orgin_table
名称 是否为空? 类型
------------------------------- -------- ---------------
ID NOT NULL NUMBER
FID NUMBER
NEW_NAME VARCHAR2(30)
CREATE_DATE DATE
COMMENTS VARCHAR2(1000)
SQL> select table_name, partition_name from user_tab_partitions where table_name = 'ORGIN_TABLE';
TABLE_NAME PARTITION_NAME
------------------------------ ------------------------------
ORGIN_TABLE P1
ORGIN_TABLE P2
SQL> select table_name, constraint_name, status from user_constraints
2 where table_name in ('ORGIN_TABLE', 'INTER_TABLE');
TABLE_NAME CONSTRAINT_NAME STATUS
-------------------- -------------------------- --------
INTER_TABLE PK_ORGIN_TABLE ENABLED
INTER_TABLE F_ORGIN_PRIMARY_ID DISABLED
ORGIN_TABLE PK_INTER_TABLE ENABLED
ORGIN_TABLE FK_INTER_PRIMARY_ID ENABLED
SQL> SELECT COUNT(*) FROM ORGIN_TABLE;
COUNT(*)
----------
4438
SQL> SELECT COUNT(*) FROM INTER_TABLE;
COUNT(*)
----------
4438
SQL> DROP TABLE INTER_TABLE;
表已丢弃。
==============================================================================================================================================================
==============================================================================
在一个高可用系统中,如果需要改变一个表的定义是一件比较棘手的问题,尤其是对于7×24系统。Oracle提供的基本语法基本可以满足一般性修改,但是对于把普通堆表改为分区表,把索引组织表修改为堆表等操作就无法完成了。而且,对于被大量DML语句访问的表,幸运的是,Oracle从9i版本开始提供了在线重定义表功能,通过调用DBMS_REDEFINITION包,可以在修改表结构的同时允许DML操作。
在线重定义表具有以下功能:
修改表的存储参数;
可以将表转移到其他表空间;
增加并行查询选项;
增加或删除分区;
重建表以减少碎片;
将堆表改为索引组织表或相反的操作;
增加或删除一个列。
调用DBMS_REDEFINITION包需要EXECUTE_CATALOG_ROLE角色,除此之外,还需要CREATE ANY TABLE、ALTER ANY TABLE、DROP ANY TABLE、LOCK ANY TABLE和SELECT ANY TABLE的权限。
在线重定义表的步骤如下:
1.选择一种重定义方法:
存在两种重定义方法,一种是基于主键、另一种是基于ROWID。ROWID的方式不能用于索引组织表,而且重定义后会存在隐藏列M_ROW$$。默认采用主键的方式。
2.调用DBMS_REDEFINITION.CAN_REDEF_TABLE()过程,如果表不满足重定义的条件,将会报错并给出原因。
3.在用一个方案中建立一个空的中间表,根据重定义后你期望得到的结构建立中间表。比如:采用分区表,增加了COLUMN等。
4.调用DBMS_REDEFINITION.START_REDEF_TABLE()过程,并提供下列参数:被重定义的表的名称、中间表的名称、列的映射规则、重定义方法。
如果映射方法没有提供,则认为所有包括在中间表中的列用于表的重定义。如果给出了映射方法,则只考虑映射方法中给出的列。如果没有给出重定义方法,则认为使用主键方式。
5.在中间表上建立触发器、索引和约束,并进行相应的授权。任何包含中间表的完整性约束应将状态置为disabled。
当重定义完成时,中间表上建立的触发器、索引、约束和授权将替换重定义表上的触发器、索引、约束和授权。中间表上disabled的约束将在重定义表上enable。
6.(可选)如果在执行DBMS_REDEFINITION.START_REDEF_TABLE()过程和执行DBMS_REDEFINITION.FINISH_REDEF_TABLE()过程直接在重定义表上执行了大量的DML操作,那么可以选择执行一次或多次的SYNC_INTERIM_TABLE()过程,以减少最后一步执行FINISH_REDEF_TABLE()过程时的锁定时间。
7.执行DBMS_REDEFINITION.FINISH_REDEF_TABLE()过程完成表的重定义。这个过程中,原始表会被独占模式锁定一小段时间,具体时间和表的数据量有关。
执行完FINISH_REDEF_TABLE()过程后,原始表重定义后具有了中间表的属性、索引、约束、授权和触发器。中间表上disabled的约束在原始表上处于enabled状态。
8.(可选)可以重命名索引、触发器和约束。对于采用了ROWID方式重定义的表,包括了一个隐含列M_ROW$$。推荐使用下列语句经隐含列置为UNUSED状态或删除。
ALTER TABLE TABLE_NAME SET UNUSED (M_ROW$$);
ALTER TABLE TABLE_NAME DROP UNUSED COLUMNS;
下面是进行重定义操作后的结果:
原始表根据中间表的属性和特性进行重定义;
START_REDEF_TABLE()和FINISH_REDEF_TABLE()操作之间在中间表上建立的触发器、索引、约束和授权,现在定义在原始表上。中间表上disabled的约束在原始表上处于enabled状态。
原始表上定义的触发器、索引、约束和授权建立在中间表上,并会在删除中间表时删除。原始表上原来enabled状态的索引,建立在中间表上,并处于disabled状态。
任何定义在原始表上的存储过程和游标都会变为INVALID,当下次调用时后自动进行编译。
如果执行过程中出现错误或者人为选择退出的话,可以执行DBMS_REDEFINITION.ABORT_REDEF_TABLE()过程。
==============================================================================================================================================================
XSB:
把一个已存在数据的大表改成分区表:
第一种(表不是太大):
1.把原表改名:
rename xsb1 to xsb2;
2.创建分区表:
CREATE TABLE xsb1
PARTITION BY LIST (c_test)
(PARTITION xsb1_p1 VALUES (1),
PARTITION xsb1_p2 VALUES (2),
PARTITION xsb1_p0 VALUES (default))
nologging AS SELECT * FROM xsb2;
3.将原表上的触发器、主键、索引等应用到分区表上;
4.删除原表:
drop table xsb2;
第二种(表很大):
1. 创建分区表:
CREATE TABLE x PARTITION BY LIST (c_test) [range ()]
(PARTITION p0 VALUES [less than ](1) tablespace tbs1,
PARTITION p2 VALUES (2) tablespace tbs1,
PARTITION xsb1_p0 VALUES ([maxvalue]default))
AS SELECT * FROM xsb2 [where 1=2];
2. 交换分区 alter table x exchange partition p0 with table bsvcbusrundatald ;
3. 原表改名alter table bsvcbusrundatald rename to x0;
4. 新表改名alter table x rename to bsvcbusrundatald ;
5. 删除原表drop table x0;
6. 创建新表触发器和索引create index ind_busrundata_lp on bsvcbusrundatald(。。。) local tablespace tbs_brd_ind ;
或者:
1. 规划原大表中数据分区的界限,原则上将原表中近期少量数据复制至另一表;
2. 暂停原大表中的相关触发器;
3. 删除原大表中近期数据;
4. 改名原大表名称;
5. 创建分区表;
6. 交换分区;
7. 重建相关索引及触发器(先删除之再重建).
参考脚本:
select count(*) from t1 where recdate>sysdate-2
create table x2 nologging as select * from t1 where recdate>trunc(sysdate-2)
alter triger trg_t1 disable
delete t1 where recdate>sysdate-2
commit
rename t1 to x1
create table t1 [nologging] partition by range(recdate)
(partition pbefore values less than (trunc(sysdate-2)),
partition pmax values less than (maxvalue))
as select * from x1 where 1=2
alter table t1 exchange partition pbefore with table x1
alter table t1 exchange partition pmax with table x2
drop table x2
[重建触发器]
drop table x1
1.1.4 参考材料:
如果表中预期的数据量较大,通常都需要考虑使用分区表,确定使用分区表后,还要确定什么类型的分区(range partition、hash partition、list partition等)、分区区间大小等。分区的创建最好与程序有某种默契,偶曾经创建分区表,按自然月份定义分区的,但程序却在查询时默认的开始时间与结束时间是:当前日期-30至当前日期,比如当天是9.18号,那查询条件被产生为8.18-9.18,结果分区后并不没有大幅提高性能,后来对程序的查询日期做了调整,按自然月查询,系统的负载小了很多。
从Oracle8.0开始支持表分区(MSSQL2005开始支持表分区)。
Oracle9i 分区能够提高许多应用程序的可管理性、性能与可用性。分区可以将表、索引及索引编排表进一步划分,从而可以更精细地对这些数据库对象进行管理和访问。Oracle 提供了种类繁多的分区方案以满足所有的业务需要。另外,由于在 SQL 语句中是完全透明的,所以分区可以用于几乎所有的应用程序。
分区表允许将数据分成被称为分区甚至子分区的更小的更好管理的块。索引也可以这么分区。每个分区可以被单独管理,可以不依赖于其他分区而单独发挥作用,因此提供了一个更有利于可用性和性能的结构。
分区可以提高可管理性、性能与可用性,从而给各种各样的应用程序带来极大的好处。通常,分区可以使某些查询以及维护操作的性能大大提高。此外,分区还能够在很大程度上简化日常管理任务。分区还使数据库设计人员和管理员能够解决尖端应用程序带来的最难的问题。分区是建立上亿万字节数据系统或需要极高可用性系统的关键工具。
在多CPU配置环境下,如果打算使用并行执行,则分区提供了另一种并行的方法。通过给表或索引的不同分区分配不同的并行执行服务器,就可以并行执行对分区表和分区索引的操作。
表或索引的分区和子分区都共享相同的逻辑属性。例如表的所有分区或子分区共享相同的列和约束定义,一个索引的分区或子分区共享相同的索引选项。然而它们可以具有不同的物理属性如表空间。
尽管不需要将表或索引的每个分区或子分区放在不同的表空间,但这样做更好。将分区存储到不同的表空间能够
l 减少数据在多个分区中冲突的可能性
l 可以单独备份和恢复每个分区
l 控制分区与磁盘驱动器之间的映射对平衡I/O 负载是重要的
l 改善可管理性可用性和性能
分区操作对现存的应用和运行在分区表上的标准DML 语句来说是透明的。但是可以通过在DML 中使用分区扩展表或索引的名字来对应用编程,使其利用分区的优点。
可以使用SQL*Loader、Import 和Export 工具来装载或卸载分区表中的数据。这些工具都是支持分区和子分区的。
分区的方法
Oracle9i 提供了如下5种分区方法:
l 范围分区Range
l 散列分区Hash
l 列表分区List
l 组合范围-散列分区Range-Hash
l 组合范围-列表分区Range-List
可对索引和表分区。全局索引只能按范围分区,但可以将其定义在任何类型的分区或非分区表上。通常全局索引比局部索引需要更多的维护。
一般组建局部索引,以便反映其基础表的结构。它与基础表是等同分区的,即它与基础
表在同样的列上分区,创建同样数量的分区或子分区,设置与基础表相对应的同样的分区边界。对局部索引而言,当维护活动影响分区时,会自动维护索引分区。这保证了索引与基础表之间的等同分区。
关于范围分区Range:
要想将行映射到基于列值范围的分区,就使用范围分区方法。当数据可以被划分成逻辑范围时如年度中的月份,这种类型的分区就有用了。当数据在整个范围中能被均等地划分时性能最好。如果靠范围的分区会由于不均等的划分而导致分区在大小上明显不同时,就需要考虑其他的分区方法。
关于散列分区Hash:
如果数据不那么容易进行范围分区,但为了性能和管理的原因又想分区时,就使用散列分区方法。散列分区提供了一种在指定数量的分区中均等地划分数据的方法。基于分区键的散列值将行映射到分区中。创建和使用散列分区会给你提供了一种很灵活的放置数据的方法,因为你可以通过在I/O 驱动器之间播撒(摘掉)这些均等定量的分区,来影响可用性和性能。
关于列表分区List:
当你需要明确地控制如何将行映射到分区时,就使用列表分区方法。可以在每个分区的描述中为该分区列指定一列离散值,这不同于范围分区,在那里一个范围与一个分区相关,这也不同于散列分区,在那里用户不能控制如何将行映射到分区。列表分区方法是特意为遵从离散值的模块化数据划分而设计的。范围分区或散列分区不那么容易做到这一点。进一步说列表分区可以非常自然地将无序的和不相关的数据集进行分组和组织到一起。
与范围分区和散列分区所不同,列表分区不支持多列分区。如果要将表按列分区,那么分区键就只能由表的一个单独的列组成,然而可以用范围分区或散列分区方法进行分区的所有的列,都可以用列表分区方法进行分区。
关于组合范围-散列分区:
范围和散列技术的组合,首先对表进行范围分区,然后用散列技术对每个范围分区再次分区。给定的范围分区的所有子分区加在一起表示数据的逻辑子集。
关于组合范围-列表分区:
范围和列表技术的组合,首先对表进行范围分区,然后用列表技术对每个范围分区再次分区。与组合范围-散列分区不同的是,每个子分区的所有内容表示数据的逻辑子集,由适当的范围和列表分区设置来描述。
创建或更改分区表时可以指定行移动子句,即ENABLE ROW MOVEMENT 或者DISABLE ROW MOVEMENT ,当其键被更改时,该子句启用或停用将行迁移到一个新的分区。默认值为DISABLE ROW MOVEMENT。本产品(项目)使用ENABLE ROW MOVEMENT子句。
分区技术能够提高数据库的可管理性:
使用分区技术,维护操作可集中于表的特定部分。例如,数据库管理员可以只对表的一部分做备份,而不必对整个表做备份。对整个数据库对象的维护操作,可以在每个分区的基础上进行,从而将维护工作分解成更容易管理的小块。
分区技术提高可管理性的一个典型用法是支持数据仓库中的‘滚动视窗’加载进程。假设数据库管理员每周向表中加载新数据。该表可以是范围分区,以便每个分区包含一周的数据。加载进程只是简单地添加新的分区。添加一个新分区的操作比修改整个表效率高很多,因为数据库管理员不需要修改任何其他分区。从分区后的表中去除数据也是一样。你只要用一个很简便快捷的数据字典操作删掉一个分区,而不必发出使用大量资源和调动所有要删除的数据的 ‘DELETE’ 命令。
分区技术能够提高数据库的性能:
由于减少了所检查或操作的数据数量,同时允许并行执行,Oracle9i 的分区功能提供了性能上的优势。这些性能包括:
l 分区修整:分区修整是用分区技术提高性能的最简单最有价值的手段。分区修整常常能够将查询性能提高几个数量级。例如,假定应用程序中有包含定单历史记录的定单表,该表用周进行了分区。查询一周的定单只需访问该定单表的一个分区。如果该定单表包含两年的历史记录,这个查询只需要访问一个而不是一百零四个分区。该查询的执行速度因为分区修整而有可能快一百倍。分区修整能与所有其他 Oracle 性能特性协作。Oracle 公司将把分区修整技术与索引技术、连结技术和并行访问方法一起联合使用。
l 分区智能联接:分区功能可以通过称为分区智能联接的技术提高多表联接的性能。当两个表要联接在一起,而且每个表都用联接关键字来分区时,就可以使用分区智能联接。分区智能联接将大型联接分解成较小的发生在各个分区间的联接,从而用较少的时间完成全部联接。这就给串行和并行的执行都能带来显著的性能改善。
l 更新和删除的并行执行:分区功能能够无限地并行执行 UPDATE、DELETE 与 MERGE 语句。当访问分区或未分区的数据库对象时Oracle 将并行处理 SELECT 与 INSERT 语句。当不使用位图索引时,也可以对分区或未分区的数据库对象并行处理 UPDATE、DELETE 和 MERGE 语句。为了对有位图索引的对象并行处理那些操作,目标表必须先分区。这些 SQL 语句的并行执行可以大大提高性能,特别是提高 UPDATE 与 DELETE 或 MERGE 操作涉及大量数据时的性能。
分区技术提高可用性:
分区的数据库对象具有分区独立性。该分区独立性特点可能是高可用性战略的一个重要部分,例如,如果分区表的分区不能用,但该表的所有其他分区仍然保持在线并可用。那么这个应用程序可以继续针对该分区表执行查询和事务处理,只要不是访问那个不可用的分区,数据库操作仍然能够成功运行。 数据库管理员可以指定各分区存放在不同的表空间里,从而让管理员独立于其它表分区针对每个分区进行备份与恢复操作。 还有,分区功能可以减少计划停机时间。性能由于分区功能得到了改善,使数据库管理员在相对较小的批处理窗口完成大型数据库对象的维护工作。
发表评论
-
oracle异常处理
2009-06-28 20:35 1946:变量名类似Pst 中 sql 的 ... -
性能优化之--------索引
2009-06-03 20:28 1143一, oracle的索引陷阱一个表中有几百万条数据,对某个字 ... -
oracle性能优化------分区技术
2009-06-02 07:08 1395数据库性能优化 Oracle方面的特性:分区技术 分区索 ... -
Oracel函数
2009-05-24 14:31 1769SQL中的单记录函数1.ASCII返回与指定的字符对应 ... -
使用JDBC插入大量数据的性能测试
2009-05-21 16:18 3075使用jdbc向数据库插入100000条记录,分别使用state ... -
Oracle的光标
2009-05-20 21:07 1208... -
OLTP和OLAP的区别
2009-05-16 12:01 1561OLTP是联机事务处理 OLAP是联机分析处理 1.用户和 ... -
如何实现网站流量设计
2009-05-14 08:08 977需求:某网站每天都有 ... -
sql性能分析
2009-05-14 07:25 1049规则:select 字句要避免使用*。 使 ... -
Oracle最快删除重复记录
2009-05-12 07:45 1459Oracle删除重复记录的最快方法:++++++++++ ... -
实际项目中是如何进行数据库建模的
2009-05-12 07:26 1073其实在实际项目中建模的精华不外乎就是以下几点,但是真正的把 ... -
悲观锁和乐观锁
2009-05-10 23:56 1361加锁对并发访问的影响体现在锁的粒度上: 1、悲观锁假定其他 ... -
怎样杀死死锁!
2009-05-10 21:49 11191、 查出是哪个过程被锁! 2、查出是哪一个sid,通过si ... -
Oracle 的树形递归查询
2009-05-10 18:01 4279一、树型表结构: 节点ID 上级ID 节点名称 二 ... -
外键的认识和理解
2009-05-05 19:18 924外键的认识和理解:++++++++++++++++++++++ ... -
导入导出1000万条数据
2009-05-05 19:07 2601如何导入导出大数据量( ... -
Oracle sql性能优化总结
2009-05-04 23:11 798选择最有效率的表名顺 ... -
rownum总结
2009-05-04 16:58 970对于 Oracle 的 rownum 问题,很多资料都说不支持 ... -
什么是数据仓库
2009-05-04 00:55 909我们都知道,利用多种 ... -
ER建模----总结
2009-04-27 08:49 1912其实、在工作中,数据库在后台这边全部设计好之后,前台就简单的多 ...
相关推荐
### Oracle 分区表总结 #### 一、Oracle分区表概述 在Oracle数据库中,分区是一种对大型表进行物理分割的方法,它可以显著提高查询性能并简化数据管理任务。通过将一个大表分成多个较小的部分(即分区),可以更快...
总结,Oracle分区表是大型数据库系统中提高性能和管理效率的重要手段。通过理解其概念、作用、优缺点以及各种分区类型,可以根据实际需求设计并实施合适的分区策略,以实现数据库的最佳性能和可扩展性。
### 导入导出Oracle分区表数据 #### 一、概述 在Oracle数据库管理中,对分区表进行数据的导入与导出是一项常见的任务。分区技术可以显著提高大型表的性能,尤其是在处理大规模数据集时。为了有效地管理和迁移这些...
根据给定的信息“清除oracle分区表数据”,我们将深入探讨如何有效地进行这项操作。 ### 分区表简介 分区是将一个大的表或索引物理地分成多个更小的部分的过程。每个部分(分区)都作为一个独立的对象来处理,这样...
总结来说,Oracle分区表是一种有效管理大规模数据的手段,通过合理分区,可以显著提升查询效率,简化维护工作,并提供更高的数据可用性。然而,使用分区也需要权衡其带来的复杂性和额外的存储需求。正确理解和应用...
### ORACLE 分区表的创建详解 #### 一、概述 在Oracle数据库中,分区是一种高效的数据管理方式,尤其适用于大型表和索引组织表。通过将数据逻辑地分割成多个独立的部分(即分区),可以显著提高查询性能,并简化表...
### Oracle 分区表与分区索引详解 #### 一、Oracle分区概述 在Oracle数据库中,分区技术是一种非常有效的管理大型表和索引的方法。通过将一个大的表或索引分成多个较小的部分(分区),可以显著提高查询性能,并...
最后,通过插入一条新记录(测试时使用,生产环境不建议操作),来验证分区表是否能够根据新数据的日期自动创建新的分区及其对应的索引。 ```sql INSERT INTO USER_ORDER (ID, CREATE_TIME) VALUES (1, ADD_MONTHS...
Oracle分区表是Oracle数据库中一种优化大数据处理的高级特性,它通过将一个大表分成多个逻辑部分,即分区,来提高查询性能、简化管理和增强可用性。分区技术在处理海量数据时尤其有用,因为它们允许数据库仅扫描与...
Oracle表分区总结 Oracle中提供了对表进行分区的机制,通过表分区,可以将表空间中数据按照某种方式分别存放到特定的分区中。
### 深入学习Oracle分区表 在Oracle数据库管理中,分区是一种重要的技术手段,能够显著提升大型数据集的查询性能。特别是在Oracle 10g版本中,支持了三种主要的分区表创建方式:范围分区(Range)、哈希分区(Hash...
例如,根据日期字段`s_time`创建一个范围分区表: ```sql CREATE TABLE t_par (s_time DATE, id NUMBER) PARTITION BY RANGE (s_time) ( PARTITION p_max VALUES LESS THAN (MAXVALUE) TABLESPACE users ); ``` 接...
### Oracle的表空间、分区表及索引的深入解析 #### 表空间(Tablespace)在Oracle中的作用与管理 表空间是Oracle数据库中的逻辑存储单元,它将数据组织成可管理的部分,允许数据库管理员更好地控制数据存储和性能...
"Oracle分区表详细解PPT课件.ppt" 本节课件将涵盖Oracle数据库的表分区的详细解释。表分区是Oracle数据库中的一种技术,用于将大型表分割成多个较小的表,提高查询速度和数据维护效率。 1. 分区表的由来 随着表中...
总结,Oracle 分区表是处理大规模数据的有效手段,通过合理选择分区策略,可以提升数据库的管理效率、可用性和性能。根据业务需求,可以选择范围、哈希、列表或复合分区等方式,以达到最佳的数据组织和查询效果。
Oracle 分区表是一种高效的数据...总结,Oracle分区表是数据库设计中的一种重要策略,它通过将大表分解为可管理的部分来优化性能和维护。了解如何创建、操作和管理这些分区对于有效地利用Oracle数据库资源至关重要。
总结来说,"Oracle数据库表按年分区脚本实战例子"是学习和实践Oracle数据库分区的一个实用资源,通过这个例子,我们可以深入了解如何利用分区提升数据库性能,以及如何根据业务需求定制和管理分区策略。对于处理大量...
#### 一、Oracle分区表概述 **Oracle分区表**是一种将大表分成多个较小部分的技术,这些部分称为分区。通过分区技术,可以显著提高查询性能,减少磁盘I/O操作,并简化数据库管理和维护工作。本文将详细介绍Oracle中...