oracle 表分区

oracle大数据表建分区优缺点

oracle给出的建议是按照表的大小给出的,10g的建议是2G,也就是说表的大小大于2G,那么就最好建立分区。
为什么要建立分区?主要是为了查询方便,因为如果一个表每天都有百万条记录,那么即使建立了索引,那么你要查的话,也不会很快的。
如果你建立了分区,每次查询一个分区,也就是这张表的几分之一,甚至几十分之一,那么不管怎么计算都比你查询整张表的消耗要少。而且在分区上也能建立索引的。
分区的建立最好一个原则,就是查询,这个要具体问题具体分析,有些分区的方式虽然条数不错,不过每次查询要跨越2-3个分区,这样的分区其实个人认为比较失败的。最好把最常用的查询限定在一个分区内,而且分区的条数不能过少(这个没有具体的要求,一般oracle是按照大小建议的,我忘了是多少了,还是那句话,看你的需求)

优点:

增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用;

维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可;

均衡I/O:可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能;

改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。

缺点:

分区表相关:已经存在的表没有方法可以直接转化为分区表。不过Oracle 提供了在线重定义表的功能。

或者  下面这种解决方法

1. 基础表的数据量大,查询的时候尽量避免原表扫描,可以考虑使用中间表或者物化视图,比如你要查询每年表中的用户数,可以把每一月统计的结果放在中间表,然后累加,
思想就是把大的查询拆分为若干小的查询。
2.在夜间执行一些job,生成中间表的数据,方便第2天查询。
3.如果表中数据特别多,可以考虑水平切分表下面详解,比如表中有2000w条记录,则拆分成两个结构一样的表,每一个标存在1000w条数据。
4.索引的选择。在设计表的时候就要考虑是否需要索引,不要等数据量多了再考虑。
5.还有表分区需要考虑~~~~

 

oracle的 分表 详解 -----表分区

设置表分区:根据 日期+公司编码(很多公司)建表分区

此文从以下几个方面来整理关于分区表的概念及操作:

        1.表空间及分区表的概念

        2.表分区的具体作用

        3.表分区的优缺点

        4.表分区的几种类型及操作方法

        5.对表分区的维护性操作.

(1.) 表空间及分区表的概念

表空间:
  是一个或多个数据文件的集合,所有的数据对象都存放在指定的表空间中,但主要存放的是表, 所以称作表空间。

 

分区表: 
当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区。表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个表空间(物理文件上),这样查询数据时,不至于每次都扫描整张表。

 

( 2).表分区的具体作用

Oracle的表分区功能通过改善可管理性、性能和可用性,从而为各式应用程序带来了极大的好处。通常,分区可以使某些查询以及维护操作的性能大大提高。此外,分区还可以极大简化常见的管理任务,分区是构建千兆字节数据系统或超高可用性系统的关键工具。

 

分区功能能够将表、索引或索引组织表进一步细分为段,这些数据库对象的段叫做分区。每个分区有自己的名称,还可以选择自己的存储特性。从数据库管理员的角度来看,一个分区后的对象具有多个段,这些段既可进行集体管理,也可单独管理,这就使数据库管理员在管理分区后的对象时有相当大的灵活性。但是,从应用程序的角度来看,分区后的表与非分区表完全相同,使用 SQL DML 命令访问分区后的表时,无需任何修改。

 

什么时候使用分区表:
1、表的大小超过2GB。

2、表中包含历史数据,新的数据被增加都新的分区中。

 

 (3).表分区的优缺点

表分区有以下优点: 
1、改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。

2、增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用;

3、维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可;

4、均衡I/O:可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能。

 

缺点: 
分区表相关:已经存在的表没有方法可以直接转化为分区表。不过 Oracle 提供了在线重定义表的功能。

 

(4).表分区的几种类型及操作方法

 一.范围分区:
范围分区将数据基于范围映射到每一个分区,这个范围是你在创建分区时指定的分区键决定的。这种分区方式是最为常用的,并且分区键经常采用日期。举个例子:你可能会将销售数据按照月份进行分区。

当使用范围分区时,请考虑以下几个规则:

1、每一个分区都必须有一个VALUES LESS THEN子句,它指定了一个不包括在该分区中的上限值。分区键的任何值等于或者大于这个上限值的记录都会被加入到下一个高一些的分区中。

2、所有分区,除了第一个,都会有一个隐式的下限值,这个值就是此分区的前一个分区的上限值。

3、在最高的分区中,MAXVALUE被定义。MAXVALUE代表了一个不确定的值。这个值高于其它分区中的任何分区键的值,也可以理解为高于任何分区中指定的VALUE LESS THEN的值,同时包括空值。

例一:

假设有一个CUSTOMER表,表中有数据200000行,我们将此表通过CUSTOMER_ID进行分区,每个分区存储100000行,我们将每个分区保存到单独的表空间中,这样数据文件就可以跨越多个物理磁盘。下面是创建表和分区的代码,如下:

CREATE TABLE CUSTOMER 

    CUSTOMER_ID NUMBER NOT NULL PRIMARY KEY, 
    FIRST_NAME  VARCHAR2(30) NOT NULL, 
    LAST_NAME   VARCHAR2(30) NOT NULL, 
    PHONE        VARCHAR2(15) NOT NULL, 
    EMAIL        VARCHAR2(80), 
    STATUS       CHAR(1) 

PARTITION BY RANGE (CUSTOMER_ID) 

    PARTITION CUS_PART1 VALUES LESS THAN (100000) TABLESPACE CUS_TS01, 
    PARTITION CUS_PART2 VALUES LESS THAN (200000) TABLESPACE CUS_TS02 
)

例二:按时间划分

CREATE TABLE ORDER_ACTIVITIES 

    ORDER_ID      NUMBER(7) NOT NULL, 
    ORDER_DATE    DATE, 
    TOTAL_AMOUNT NUMBER, 
    CUSTOTMER_ID NUMBER(7), 
    PAID           CHAR(1) 

PARTITION BY RANGE (ORDER_DATE) 
(

  PARTITION ORD_ACT_PART01 VALUES LESS THAN (TO_DATE('01- MAY -2003','DD-MON-YYYY')) TABLESPACEORD_TS01,

  PARTITION ORD_ACT_PART02 VALUES LESS THAN (TO_DATE('01-JUN-2003','DD-MON-YYYY')) TABLESPACE ORD_TS02,

  PARTITION ORD_ACT_PART02 VALUES LESS THAN (TO_DATE('01-JUL-2003','DD-MON-YYYY')) TABLESPACE ORD_TS03

)

例三:MAXVALUE

CREATE TABLE RangeTable

  idd   INT PRIMARY KEY , 
  iNAME VARCHAR(10), 
  grade INT  

PARTITION  BY  RANGE (grade) 

      PARTITION  part1 VALUES  LESS  THEN (1000) TABLESPACE  Part1_tb, 
      PARTITION  part2 VALUES  LESS  THEN (MAXVALUE) TABLESPACE  Part2_tb 
);

 

.列表分区:

该分区的特点是某列的值只有几个,基于这样的特点我们可以采用列表分区。

例一

CREATE TABLE PROBLEM_TICKETS 

    PROBLEM_ID   NUMBER(7) NOT NULL PRIMARY KEY, 
    DESCRIPTION  VARCHAR2(2000), 
    CUSTOMER_ID  NUMBER(7) NOT NULL, 
    DATE_ENTERED DATE NOT NULL, 
    STATUS       VARCHAR2(20) 

PARTITION BY LIST (STATUS) 

      PARTITION PROB_ACTIVE   VALUES ('ACTIVE') TABLESPACE PROB_TS01, 
      PARTITION PROB_INACTIVE VALUES ('INACTIVE') TABLESPACE PROB_TS02

例二

CREATE  TABLE  ListTable

    id    INT  PRIMARY  KEY , 
    name  VARCHAR (20), 
    area  VARCHAR (10) 

PARTITION  BY  LIST (area) 

    PARTITION  part1 VALUES ('guangdong','beijing') TABLESPACE  Part1_tb, 
    PARTITION  part2 VALUES ('shanghai','nanjing')  TABLESPACE  Part2_tb 
);

)

 

.散列分区:
这类分区是在列值上使用散列算法,以确定将行放入哪个分区中。当列的值没有合适的条件时,建议使用散列分区。

散列分区为通过指定分区编号来均匀分布数据的一种分区类型,因为通过在I/O设备上进行散列分区,使得这些分区大小一致。

例一:

CREATE TABLE HASH_TABLE 

  COL NUMBER(8), 
  INF VARCHAR2(100) 

PARTITION BY HASH (COL) 

  PARTITION PART01 TABLESPACE HASH_TS01, 
  PARTITION PART02 TABLESPACE HASH_TS02, 
  PARTITION PART03 TABLESPACE HASH_TS03 
)

简写:

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);

 

hash分区最主要的机制是根据hash算法来计算具体某条纪录应该插入到哪个分区中,hash算法中最重要的是hash函数,Oracle中如果你要使用hash分区,只需指定分区的数量即可。建议分区的数量采用2的n次方,这样可以使得各个分区间数据分布更加均匀。

 

.组合范围散列分区
这种分区是基于范围分区和列表分区,表首先按某列进行范围分区,然后再按某列进行列表分区,分区之中的分区被称为子分区。

CREATE TABLE SALES 
(

PRODUCT_ID VARCHAR2(5),

SALES_DATE DATE,

SALES_COST NUMBER(10),

STATUS VARCHAR2(20)

)

PARTITION BY RANGE(SALES_DATE) SUBPARTITION BY LIST (STATUS)

(

   PARTITION P1 VALUES LESS THAN(TO_DATE('2003-01-01','YYYY-MM-DD'))TABLESPACE rptfact2009 
          ( 
              SUBPARTITION P1SUB1 VALUES ('ACTIVE') TABLESPACE rptfact2009, 
              SUBPARTITION P1SUB2 VALUES ('INACTIVE') TABLESPACE rptfact2009 
          ), 
   PARTITION P2 VALUES LESS THAN (TO_DATE('2003-03-01','YYYY-MM-DD')) TABLESPACE rptfact2009 
          ( 
              SUBPARTITION P2SUB1 VALUES ('ACTIVE') TABLESPACE rptfact2009, 
              SUBPARTITION P2SUB2 VALUES ('INACTIVE') TABLESPACE rptfact2009 
          ) 
)

 

.复合范围散列分区:

这种分区是基于范围分区和散列分区,表首先按某列进行范围分区,然后再按某列进行散列分区。

create table dinya_test 
 ( 
 transaction_id number primary key, 
 item_id number(8) not null, 
 item_description varchar2(300), 
 transaction_date date 
 ) 
 partition by range(transaction_date)subpartition by hash(transaction_id)  subpartitions 3 store in (dinya_space01,dinya_space02,dinya_space03) 
 ( 
     partition part_01 values less than(to_date(‘2006-01-01’,’yyyy-mm-dd’)), 
     partition part_02 values less than(to_date(‘2010-01-01’,’yyyy-mm-dd’)), 
     partition part_03 values less than(maxvalue) 
 );

 

(5).有关表分区的一些维护性操作: 
一、添加分区 
以下代码给SALES表添加了一个P3分区

ALTER TABLE SALES ADD PARTITION P3 VALUES LESS THAN(TO_DATE('2003-06-01','YYYY-MM-DD'));

注意:以上添加的分区界限应该高于最后一个分区界限。

以下代码给SALES表的P3分区添加了一个P3SUB1子分区

ALTER TABLE SALES MODIFY PARTITION P3 ADD SUBPARTITION P3SUB1 VALUES('COMPLETE');

二、删除分区 
以下代码删除了P3表分区:

ALTER TABLE SALES DROP PARTITION P3;

在以下代码删除了P4SUB1子分区:

ALTER TABLE SALES DROP SUBPARTITION P4SUB1;

注意:如果删除的分区是表中唯一的分区,那么此分区将不能被删除,要想删除此分区,必须删除表。

三、截断分区 
截断某个分区是指删除某个分区中的数据,并不会删除分区,也不会删除其它分区中的数据。当表中即使只有一个分区时,也可以截断该分区。通过以下代码截断分区:

ALTER TABLE SALES TRUNCATE PARTITION P2;

通过以下代码截断子分区:

ALTER TABLE SALES TRUNCATE SUBPARTITION P2SUB2;

四、合并分区 
合并分区是将相邻的分区合并成一个分区,结果分区将采用较高分区的界限,值得注意的是,不能将分区合并到界限较低的分区。以下代码实现了P1 P2分区的合并:

ALTER TABLE SALES MERGE PARTITIONS P1,P2 INTO PARTITION P2;

五、拆分分区 
拆分分区将一个分区拆分两个新分区,拆分后原来分区不再存在。注意不能对HASH类型的分区进行拆分。

ALTER TABLE SALES SBLIT PARTITION P2 AT(TO_DATE('2003-02-01','YYYY-MM-DD')) INTO (PARTITION P21,PARTITION P22);

六、接合分区(coalesca) 
结合分区是将散列分区中的数据接合到其它分区中,当散列分区中的数据比较大时,可以增加散列分区,然后进行接合,值得注意的是,接合分区只能用于散列分区中。通过以下代码进行接合分区:

ALTER TABLE SALES COALESCA PARTITION;

七、重命名表分区 
以下代码将P21更改为P2

ALTER TABLE SALES RENAME PARTITION P21 TO P2;

八、相关查询
跨分区查询

select sum( *) from

(select count(*) cn from t_table_SS PARTITION (P200709_1)

union all

select count(*) cn from t_table_SS PARTITION (P200709_2)

);

查询表上有多少分区

SELECT * FROM useR_TAB_PARTITIONS WHERE TABLE_NAME='tableName'

查询索引信息

select object_name,object_type,tablespace_name,sum(value)

from v$segment_statistics

where statistic_name IN ('physical reads','physical write','logical reads')and object_type='INDEX'

group by object_name,object_type,tablespace_name

order by 4 desc

 

--显示数据库所有分区表的信息:

select * from DBA_PART_TABLES

 

--显示当前用户可访问的所有分区表信息:

select * from ALL_PART_TABLES

 

--显示当前用户所有分区表的信息:

select * from USER_PART_TABLES

 

--显示表分区信息 显示数据库所有分区表的详细分区信息:

select * from DBA_TAB_PARTITIONS

 

--显示当前用户可访问的所有分区表的详细分区信息:

select * from ALL_TAB_PARTITIONS

 

--显示当前用户所有分区表的详细分区信息:

select * from USER_TAB_PARTITIONS

 

--显示子分区信息 显示数据库所有组合分区表的子分区信息:

select * from DBA_TAB_SUBPARTITIONS

 

--显示当前用户可访问的所有组合分区表的子分区信息:

select * from ALL_TAB_SUBPARTITIONS

 

--显示当前用户所有组合分区表的子分区信息:

select * from USER_TAB_SUBPARTITIONS

 

--显示分区列 显示数据库所有分区表的分区列信息:

select * from DBA_PART_KEY_COLUMNS

 

--显示当前用户可访问的所有分区表的分区列信息:

select * from ALL_PART_KEY_COLUMNS

 

--显示当前用户所有分区表的分区列信息:

select * from USER_PART_KEY_COLUMNS

 

--显示子分区列 显示数据库所有分区表的子分区列信息:

select * from DBA_SUBPART_KEY_COLUMNS

 

--显示当前用户可访问的所有分区表的子分区列信息:

select * from ALL_SUBPART_KEY_COLUMNS

 

--显示当前用户所有分区表的子分区列信息:

select * from USER_SUBPART_KEY_COLUMNS

 

--怎样查询出oracle数据库中所有的的分区表

select * from user_tables a where a.partitioned='YES'

 

--删除一个表的数据是

truncate table table_name;

 

--删除分区表一个分区的数据是

alter table table_name truncate partition p5;

 

 

oracle分区表按时间自动创建

表分区是一种思想,分区表示一种技术实现。当表的大小过G的时候可以考虑进行表分区,提高查询效率,均衡IO。oracle分区表是oracle数据库提供的一种表分区的实现形式。表进行分区后,逻辑上仍然是一张表,原来的查询SQL同样生效,同时可以采用使用分区查询来优化SQL查询效率,不至于每次都扫描整个表。

根据年: INTERVAL(NUMTOYMINTERVAL(1,'YEAR'))
根据月: INTERVAL(NUMTOYMINTERVAL(1,'MONTH'))
根据天: INTERVAL(NUMTODSINTERVAL(1,'DAY'))
根据时分秒: NUMTODSINTERVAL( n, { 'DAY'|'HOUR'|'MINUTE'|'SECOND'})

此时已经有普通表了,我创建了含相同字段的分区表,把数据导入到分区表中,再把原表删掉。

-- Create table(WMS_OPERATION_RECORD)create table DPHOMEWMS.WMS_OPERATION_RECORD_TMP

(

  ID             NUMBER(19) not null,

  WAREHOUSE_ID   NUMBER(19),

  ASN_ID         NUMBER(19),

  PICK_TICKET_ID NUMBER(19),

  RELATION_CODE  VARCHAR2(50),

  OPERATION_TYPE VARCHAR2(50),

  OPERATION_ID   NUMBER(19),

  OPERATION_NAME VARCHAR2(50 CHAR),

  OPERATION_TIME TIMESTAMP(6) DEFAULT systimestamp not null,

  STATUS         VARCHAR2(10),

  TYPE           VARCHAR2(10),

  COUNTS         NUMBER(10)

)tablespace DPHOMEWMS_DATA

PARTITION BY RANGE (OPERATION_TIME) interval (numtoyminterval(1, 'month'))

STORE IN (DPHOMEWMS_DATA)

(

  partition OPERATION_RECORD_P01 values less than (TIMESTAMP' 2017-05-08 00:00:00')

  tablespace DPHOMEWMS_DATA

);-- Add comments to the columns

comment on column DPHOMEWMS.WMS_OPERATION_RECORD_TMP.WAREHOUSE_ID

  is '仓库id';

comment on column DPHOMEWMS.WMS_OPERATION_RECORD_TMP.ASN_ID

  is '收货单id';

comment on column DPHOMEWMS.WMS_OPERATION_RECORD_TMP.PICK_TICKET_ID

  is '发货单ID';

comment on column DPHOMEWMS.WMS_OPERATION_RECORD_TMP.RELATION_CODE

  is '关联单据号(收货单或发货单的code)';

comment on column DPHOMEWMS.WMS_OPERATION_RECORD_TMP.OPERATION_TYPE

  is '操作类型';

comment on column DPHOMEWMS.WMS_OPERATION_RECORD_TMP.OPERATION_ID

  is '操作人ID';

comment on column DPHOMEWMS.WMS_OPERATION_RECORD_TMP.OPERATION_NAME

  is '操作人名称';

comment on column DPHOMEWMS.WMS_OPERATION_RECORD_TMP.OPERATION_TIME

  is '操作时间';

comment on column DPHOMEWMS.WMS_OPERATION_RECORD_TMP.STATUS

  is '状态';

comment on column DPHOMEWMS.WMS_OPERATION_RECORD_TMP.TYPE

  is '明细或者统计次数类型';

comment on column DPHOMEWMS.WMS_OPERATION_RECORD_TMP.COUNTS

  is '统计次数';--创建本地索引create index IDX_WMS_OPERATION_RECORD  on DPHOMEWMS.WMS_OPERATION_RECORD_TMP(RELATION_CODE)

tablespace DPHOMEWMS_INDEX local;update DPHOMEWMS.WMS_OPERATION_RECORD set OPERATION_TIME = sysdate where OPERATION_TIME is null;insert into DPHOMEWMS.WMS_OPERATION_RECORD_TMP select * from WMS_OPERATION_RECORD;drop table DPHOMEWMS.WMS_OPERATION_RECORD;alter table DPHOMEWMS.WMS_OPERATION_RECORD_TMP rename to WMS_OPERATION_RECORD;alter table DPHOMEWMS.WMS_OPERATION_RECORD enable row movement;

1)OPERATION_TIME是分区键,每一个月会自动创建一个分区,分区键不允许为null。

2)alter table table_name enable row movement;    是指允许分区表的分区键是可更新,当某一行更新时,如果更新的是分区列,并且更新后的列值不属于原来的这个分区,如果开启了这个选项,就会把这行从这个分区中delete掉,并加到更新后所属的分区,此时就会发生rowid的改变。相当于一个隐式的delete+insert,但是不会触发insert/delete触发器。如果没有开启这个选项,就会在更新时报错。

oracle定期生成和删除表分区

在项目中我们有个一个表是秒数据表,这个表每天插入的数据量都有800多万条,所以我们只存储一段时间的数据,半个月之前的数据就会删除掉,这样当我们查询当前即时的数据来绘制图表的时候就会出现问题:Oralce的高水位线的问题。

至于什么是高水位线问题,大家可以百度下,这里摘抄一段:

oracle里,使用delete删除数据以后,数据库的存储容量不会减少,而且使用delete删除某个表的数据以后,查询这张表的速度和删除之前一样,不会发生变化。 

    因为oralce有一个HWM高水位,它是oracle的一个表使用空间最高水位线。当插入了数据以后,高水位线就会上涨,但是如果你采用delete语句删除数据的话,数据虽然被删除了,但是高水位线却没有降低,还是你刚才删除数据以前那么高的水位。除非使用truncate删除数据。那么,这条高水位线在日常的增删操作中只会上涨,不会下跌,所以数据库容量也只会上升,不会下降。而使用select语句查询数据时,数据库会扫描高水位线以下的数据块,因为高水位线没有变化,所以扫描的时间不会减少,所以才会出现使用delete删除数据以后,查询的速度还是和delete以前一样。

    在网上查了下,决定用表分区来解决这个问题,方案就是每天定期新建表分区,同时删除旧的表分区。

首先,新建表和分区

[sql] view plain copy

1.  CREATE TABLE "DATASERVER"."SVRSENSORDATA"   

2.   ( "ID" NUMBER(*,0) DEFAULT 0 NOT NULL ENABLE,   

3. "SSID" NUMBER(*,0) DEFAULT 0 NOT NULL ENABLE,   

4. "TYPE" NUMBER(*,0) DEFAULT 0 NOT NULL ENABLE,   

5. "VALUE" BINARY_DOUBLE DEFAULT 0,   

6. "TIME" TIMESTAMP (3) NOT NULL ENABLE,   

7.   )PARTITION BY RANGE (TIME)  --以TIME字段做分区条件  

8.  (  

9.            partition SDP_20140302 values less than (to_date('2014/03/02','YYYY/MM/DD')),  

10.            partition SDP_20140303 values less than (to_date('2014/03/03','YYYY/MM/DD')),  

11.            partition SDP_20500101 values less than (maxvalue)  

12.  );  


这里新建了表和表分区,然后要做的就是每天都新建一个新的表分区。  

建立添加新表分区的存储过程

[sql] view plain copy

1. create or replace  

2. PROCEDURE SVRSENSORDATA_ADDPART(  

3.   DaysAmount NUMBER  --要添加多少天之后的分区  

4. )  

5. AS  

6.  v_SqlExec VARCHAR2(2000); --DDL语句变量  

7.  v_PartName VARCHAR2(20);--创建分区的日期(YYYYMMDD)  

8.  v_PartDateStr VARCHAR2(20);--分区时间的字符串形式  

9.  begin  

10.  v_PartName:= 'SDP_' +to_char(sysdate +  DaysAmount,'YYYYMMDD');  

11.  v_partdatestr:= to_char(sysdate +  DaysAmount, 'YYYY-MM-DD');  

12.  v_SqlExec:='alter table SVRSENSORDATA SPLIT partition SDP_20500101 at (to_date('||v_PartDateStr||',''YYYY-MM-DD'')) INTO  (PARTITION '||v_PartName||', PARTITION SDP_20500101)';  

13.  DBMS_Utility.Exec_DDL_Statement(v_SqlExec);  

14.  END SVRSENSORDATA_ADDPART;  


建立删除分区的存储过程

[sql] view plain copy

1. create or replace  

2. PROCEDURE SVRSENSORDATA_DROPPART(  

3.   DaysAmount NUMBER --删除间隔日期  

4. )   

5. AS  

6.  v_SqlExec VARCHAR2(2000); --DDL语句变量  

7.  --先查找DaysAmount之前的表分区  

8.  cursor cursor_part is  

9.  select partition_name from user_tab_partitions  

10.  WHERE table_name= 'SVRSENSORDATA' AND to_date(SUBSTR(partition_name,5,8),'YYYYMMDD')< sysdate- daysamount order by partition_name;  

11.  cursor_oldpart cursor_part%rowType;  

12.  begin  

13.  open cursor_part;  

14.    loop  

15.    fetch cursor_part into cursor_oldpart;  

16.    exit when cursor_part%notfound;  

17.    v_sqlexec:='ALTER TABLE SVRSENSORDATA DROP PARTITION '||cursor_oldpart.partition_name;  

18.    DBMS_Utility.Exec_DDL_Statement(v_SqlExec);  

19.    end loop;  

20.    close cursor_part;  

21.  END SVRSENSORDATA_DROPPART;  

 

然后使用Oracle job 每天定期执行一次这两个过程。

数据库表的垂直拆分和水平拆分

垂直拆分

垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表


通常我们按以下原则进行垂直拆分:

1. 把不常用的字段单独放在一张表;

2. text,blob等大字段拆分出来放在附表中;

3. 经常组合查询的列放在一张表中;垂直拆分更多时候就应该在数据表设计之初就执行的步骤,然后查询的时候用join关键起来即可;

水平拆分

水平拆分是指数据表行的拆分,表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放。

水平拆分的一些技巧

1. 拆分原则
通常情况下,我们使用取模的方式来进行表的拆分;比如一张有400W的用户表users,为提高其查询效率我们把其分成4张表

users1,users2,users3,users4
通过用ID取模的方法把数据分散到四张表内Id%4+1 = [1,2,3,4]
这里是个小哈希,然后查询,更新,删除也是通过取模的方法来查询

$_GET['id'] = 17,17%4 + 1 = 2,  $tableName = 'users'.'2'

Select * from users2 where id = 17;

insert时还需要一张临时表uid_temp来提供自增的ID,该表的唯一用处就是提供自增的ID;

insert into uid_temp values(null);

得到自增的ID后,又通过取模法进行分表插入;
注意,进行水平拆分后的表,字段的列和类型和原表应该是相同的,但是要记得去掉auto_increment自增长

另外
部分业务逻辑也可以通过地区,年份等字段来进行归档拆分;
进行拆分后的表,只能满足部分查询的高效查询需求,这时我们就要在产品策划上,从界面上约束用户查询行为。比如我们是按年来进行归档拆分的,这个时候在页面设计上就约束用户必须要先选择年,然后才能进行查询;
在做分析或者统计时,由于是自己人的需求,多点等待其实是没关系的,并且并发很低,这个时候可以用union把所有表都组合成一张视图来进行查询,然后再进行查询;

Create view users as select from users1 union select from users2 union.........

 

支持自动ORACLE分区: 版本进度: 31. 20110420 V2.2 支持任意任意时间字段分区 以下为安装部署部分: 1.分区相关脚本部署执行顺序,安装前请确保该用户拥有管理员权限, 同时请执行GRANT CREATE ANY TABLE TO DBUSER, 因为使用到了动态的CREATE TABLE语句; 01) >AGGRE_ERROR_INFO_DDL.SQL 如果日志AGGRE_ERROR_INFO已经存在,该步骤跳过。 02) >GET_MILLISECOND.SQL 如果函数GET_MILLISECOND已经存在,该步骤跳过。 03) >GET_DATE_FROM_MILLISECOND.SQL 如果函数GET_DATE_FROM_MILLISECOND已经存在,该步骤跳过。 04) >AGGRE_PM_PARTITIONF.SQL 2.注意事项: 01) >部署完后注意检查分区维护JOB[对应存储过程为AGGRE_PM_PARTITIONM], 如果有多个相同的分区维护JOB,则请删除后面创建的JOB,只保留一个分区维护JOB。 检查脚本如下:select t.what,t.* from user_jobs t 02) >本产品中使用的分区调度名称为AGGRE_PARTITION_TASK,可以根据该中信息观察分区情况。 以下为说明解释部分: 2.分区改造主过程:AGGRE_PM_PARTITIONF.SQL, 意思是PARTITIONING THE FIRST TIME; 参数解释如下: -- @PARAM VARCHAR2 PARTTABLENAME---可以指定对某个大小大于等于TABLEONSIZE_M(单位为MB)的进行按指定时间字段的自动分区; -- @PARAM NUMBER TABLEONSIZE_M---大自动分区起始大小,单位为兆字节(MB),如不想指定具体大小则置0即可; -- @PARAM NUMBER PARTINTERVAL----取值范围为[1/24,365],分区时长,单位为天,默认为1,采用一天一分区; -- @PARAM 若为7,则采用一周一分区,若为30,则采用一月一分区; -- @PARAM NUMBER PARTRESERVED----数据保留时长,单位为天; -- @PARAM NUMBER BACKINTERVAL----取值范围为[3600,7*86400],数据回迁时的循环步长,即一次回迁多长时间的数据,单位为秒; -- @PARAM VARCHAR2 PARTWEEKDAY-----取值范围为(SUN,MON),PARTINTERVAL为7时起作用,指定一周的起始天为星期日还是星期一; -- @PARAM VARCHAR2 PARTFIELD-------指定的分区时间字段名称 -- @PARAM VARCHAR2 FIELDFORMAT-----指定的分区时间字段的格式 -- @PARAM VARCHAR2 TISPARTITIONED--取值范围为(TRUE,FALSE),指定PARTTABLENAME参数所指定的是否是分区,默认为FALSE -- @PARAM VARCHAR2 PARTEXCHANGE----取值范围为(TRUE,FALSE),是否使用交换分区方法实现非分区分区化改造,默认为FALSE -- @PARAM 注意:当PARTEXCHANGE参数为TRUE时,TISPARTITIONED参数只能为FALSE, -- @PARAM 即已经分好区的分区是不能够使用交换分区的方法转换为另一种分区的; -- @PARAM VARCHAR2 DROPPABLE-------取值范围为(TRUE,FALSE),指定分区完后是否DROP掉分区备份; 其中参数FIELDFORMAT的取值范围如下: /** * FIELDFORMAT * 0 NUMBER/CHAR MILLISECOND 1300200064000 13BITS * 1 NUMBER/CHAR SECOND 1300200064 10BITS * 2 NUMBER/CHAR YYYYMMDDHH24MISS 20110315224030 * 3 NUMBER/CHAR YYYYMMDDHH24MI 201103152240 * 4 NUMBER/CHAR YYYYMMDDHH24 2011031522 * 5 NUMBER/CHAR YYYYMMDD 20110315 * 6 NUMBER/CHAR YYYYMM 201103 * 7 NUMBER/CHAR YYYY 2011 * 8 CHAR YYYY-MM 2011-03 * 9 CHAR YYYY-MM-DD 2011-03-15 * 10 CHAR YYYY-MM-DD HH24 2011-03-15 22 * 11 CHAR YYYY-MM-DD HH24:MI 2011-03-15 22:40 * 12 CHAR YYYY-MM-DD HH24:MI:SS 2011-03-15 22:40:30 * 13 CHAR YYYY-MM-DD HH24:MI:SSXFF 2011-03-15 22:40:30.765000 * 14 CHAR YYYY"年" 2011年 * 15 CHAR YYYY"年"MM"月" 2011年03月 * 16 CHAR YYYY"年"MM"月"DD"日" 2011年03月15日 * 17 CHAR YYYY"年"MM"月"DD"日" HH24"时" 2011年03月15日 22时 * 18 CHAR YYYY"年"MM"月"DD"日" HH24"时"MI"分" 2011年03月15日 22时40分 * 19 CHAR YYYY"年"MM"月"DD"日" HH24"时"MI"分"SS"秒" 2011年03月15日 22时40分30秒 * 100 DATE 2011-3-15 23:00:01 * 101 TIMESTAMP 15-3月 -11 10.59.30.953000 下午 +08:00 */ -- 第一次分区尽量在数据库闲时操作,这样更能保证分区的数据一致性; -- 通常使用的现有大分区方法:A.使用RENAME分区 B.使用交换分区 C.使用联机重定义 只有C方案才能保证数据的完全一致性; -- 但是经过测试发现方案B和C都存在分区过程的不透明性,对EXCEPTION不好控制,另外C方案比较适合手工操作,不适合自动运行; -- B方案比较适合将非分区中的数据放到分区中的一个分区中,不符合要求,所以本分区存储过程默认采用A方案; -- 当然,也支持通过新增参数PARTEXCHANGE来控制是否使用B方案;PARTEXCHANGE为TRUE,使用B方案,为FALSE,使用A方案; -- 手动运行示例: 自动对800M以上的非分区PM_RAW_B_RESTEST进行分区,一天一分区; -- 手动运行示例: SQL> EXEC AGGRE_PM_PARTITIONF('PM_RAW_B_RESTEST',800,1,10,3600,'SUN','DCTIME','0','FALSE','FALSE','FALSE'); -- 推荐以以上这种方式对单个进行分区,并将DROPPABLE参数设为'FALSE', -- 这样有什么问题可以跟踪,等完后再可手动将分区备份DROP掉; -- 注意:分区之前请确保相关空间足够大。 -- 注意:如果在分区化改造过程中数据回迁之前抛出异常,则手动数据回迁前注意检查分区有无主键索引。 3.分区维护主过程:AGGRE_PM_PARTITIONM.SQL, 意思是PARTITION MANAGEMENT; 4.创建分区维护JOB -- 对在分区调度中的已经分区进行分区清理以及分区追加等 -- 分区维护操作由该JOB自动完成,该过程不用手动干预。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值