mysql建表分区按天_oracle表分区详解(按天、按月、按年等)

本文介绍了数据库分区的概念、优点和三种主要分区方式:范围分区、Hash分区和List分区,通过实例详细讲解了如何在MySQL和Oracle中创建按天、月、年等不同粒度的分区表,包括组合分区和Oracle 11g的Interval分区,以提高查询性能和数据管理效率。
摘要由CSDN通过智能技术生成

分区表的概念:

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

分区表的优点:

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

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

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

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

分区表的种类:

1.范围分区

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

-- 按行分区

SQL> CREATE TABLE part_andy1

2  (

3      andy_ID NUMBER NOT NULL PRIMARY KEY,

4      FIRST_NAME  VARCHAR2(30) NOT NULL,

5      LAST_NAME   VARCHAR2(30) NOT NULL,

6      PHONE        VARCHAR2(15) NOT NULL,

7      EMAIL        VARCHAR2(80),

8      STATUS       CHAR(1)

9  )

10  PARTITION BY RANGE (andy_ID)

11  (

12      PARTITION PART1 VALUES LESS THAN (10000) ,

13      PARTITION PART2 VALUES LESS THAN (20000)

14  );

Table created.

-- 按时间分区

SQL> CREATE TABLE part_andy2

2  (

3  ORDER_ID      NUMBER(7) NOT NULL,

4  ORDER_DATE    DATE,

5  OTAL_AMOUNT NUMBER,

6  CUSTOTMER_ID NUMBER(7),

7  PAID           CHAR(1)

8  )

9  PARTITION BY RANGE (ORDER_DATE)

10  (

11    PARTITION p1 VALUES LESS THAN (TO_DATE('2014-10-1', 'yyyy-mm-dd')) ,

12    PARTITION p2 VALUES LESS THAN (TO_DATE('2015-10-1', 'yyyy-mm-dd')) ,

13    PARTITION p3 VALUES LESS THAN (TO_DATE('2016-10-1', 'yyyy-mm-dd')) ,

14    partition p4 values less than (maxvalue)

15  );

Table created.

2.  Hash分区

概念:

对于那些无法有效划分范围的表,可以使用hash分区,这样对于提高性能还是会有一定的帮助。hash分区会将表中的数据平均分配到你指定的几个分区中,列所在分区是依据分区列的hash值自动分配,因此你并不能控制也不知道哪条记录会被放到哪个分区中,hash分区也可以支持多个依赖列。

注意:

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

--按hash分区

SQL> create table part_andy3

2  (

3  transaction_id number primary key,

4  item_id number(8) not null

5  )

6  partition by hash(transaction_id)

7  (

8  partition part_01 ,

9  partition part_02 ,

10  partition part_03

11  );

Table created.

3.  List分区

概念:

List分区也需要指定列的值,其分区值必须明确指定,该分区列只能有一个,不能像range或者hash分区那样同时指定多个列做为分区依赖列,但它的单个分区对应值可以是多个。

注意:

在分区时必须确定分区列可能存在的值,一旦插入的列值不在分区范围内,则插入/更新就会失败,因此通常建议使用list分区时,要创建一个default分区存储那些不在指定范围内的记录,类似range分区中的maxvalue分区。

-- 按list分区

SQL> create table part_andy4

2  (

3  id varchar2(15 byte) not null,

4  city varchar2(20)

5  )

6  partition by list (city)

7  (

8  partition t_list025 values ('beijing'),

9  partition t_list372 values ('shanghai') ,

10  partition t_list510 values ('changsha'),

11  partition p_other values (default)

12  );

Table created.

4. 组合分区

Oracle10g提供两种分区组合

– Range-hash

SQL> create table part_andy5

2  (

3  transaction_id number primary key,

4  item_id number(8) not null,

5  item_description varchar2(300),

6  transaction_date date

7  )

8  partition by range(transaction_date)subpartition by hash(transaction_id)

9  (

10  partition part_01 values less than(TO_DATE('2014-10-1', 'yyyy-mm-dd')),

11  partition part_02 values less than(TO_DATE('2015-10-1', 'yyyy-mm-dd')),

12  partition part_03 values less than(maxvalue)

13  );

Table created.

– Range-list

SQL> CREATE TABLE SALES

2  (

3  PRODUCT_ID VARCHAR2(5),

4  SALES_DATE DATE,

5  SALES_COST NUMBER(10),

6  STATUS VARCHAR2(20)

7  )

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

9  (

10  PARTITION P1 VALUES LESS THAN(TO_DATE('2014-10-1', 'yyyy-mm-dd'))

11  (SUBPARTITION P1SUB1 VALUES ('ACTIVE') ,SUBPARTITION P1SUB2 VALUES ('INACTIVE')

12  ),PARTITION P2 VALUES LESS THAN (TO_DATE('2015-10-1', 'yyyy-mm-dd'))

13  (

14  SUBPARTITION P2SUB1 VALUES ('ACTIVE') ,

15  SUBPARTITION P2SUB2 VALUES ('INACTIVE')

16  )

17  );

Table created.

Oracle11g增加了四种组合

– RANGE-RANGE

– LIST-RANGE

– LIST-HASH

– LIST-LIST

Oracle 11g 中虚拟列来实现。在11g之前 分区表的partition key必须是物理存在的。11g开始提供了虚拟列,并且可以作为partition key 。

--按星期分区

SQL> CREATE TABLE part_andy6

2  (

3  getdate   date NOT NULL,

4  wd        NUMBER GENERATED ALWAYS AS (TO_NUMBER (TO_CHAR (getdate, 'D'))) VIRTUAL

5  )

6  PARTITION BY LIST (wd)

7  (

8  PARTITION Mon  VALUES (1),

9  PARTITION Tue  VALUES (2),

10  PARTITION Wed  VALUES (3),

11  PARTITION Thu  VALUES (4),

12  PARTITION Fri  VALUES (5),

13  PARTITION Sat   VALUES (6),

14  PARTITION Sun  VALUES (7)

15  );

Table created.

SQL>

SQL> insert into part_andy6(getdate) values(sysdate);

1 row created.

SQL> insert into part_andy6(getdate) values(sysdate-1);

1 row created.

SQL> insert into part_andy6(getdate) values(sysdate-2);

1 row created.

SQL> insert into part_andy6(getdate) values(sysdate-3);

1 row created.

SQL> insert into part_andy6(getdate) values(sysdate-4);

1 row created.

SQL> insert into part_andy6(getdate) values(sysdate-5);

1 row created.

SQL> insert into part_andy6(getdate) values(sysdate-6);

1 row created.

SQL> insert into part_andy6(getdate) values(sysdate-7);

1 row created.

-- 检查测试成功

SQL> select * from part_andy6;

GETDATE                     WD

------------------- ----------

2014-11-23 16:35:07          1

2014-11-24 16:35:07          2

2014-11-25 16:35:07          3

2014-11-26 16:35:07          4

2014-11-27 16:35:07          5

2014-11-28 16:35:07          6

2014-11-29 16:35:07          7

2014-11-22 16:35:08          7

8 rows selected.

Oracle Database 11g,Interval类型分区表,可以根据加载数据,自动创建指定间隔的分区。

创建按月分区的分区表:

a. 创建分区表

SQL> CREATE TABLE interval_andy7 (a1 NUMBER, a2 DATE)

2  PARTITION BY RANGE (a2)

3  INTERVAL ( NUMTOYMINTERVAL (1, 'MONTH') )

4  (PARTITION part1

5  VALUES LESS THAN (TO_DATE('2014-11-1', 'yyyy-mm-dd')),

6  PARTITION part2

7  VALUES LESS THAN (TO_DATE('2014-12-1', 'yyyy-mm-dd'))

8  );

Table created.

注意:如果在建Interval分区表是没有把所有的分区写完成,在插入相关数据后会自动生成分区

b. 查看现在表的分区:

SQL> select table_name,partition_name from user_tab_partitions where table_name='INTERVAL_ANDY7';

TABLE_NAME                     PARTITION_NAME

------------------------------ ------------------------------

INTERVALPART                   PART1

INTERVALPART                   PART2

c.  插入测试数据:

SQL> begin

2  for i in 0 .. 11 loop

3  insert into interval_andy7 values(i,add_months(to_date('2014-11-1','yyyy-mm-dd'),i));

4  end loop ;

5  commit;

6  end;

7  /

PL/SQL procedure successfully completed.

PL/SQL 过程已成功完成。

补充:add_months()函数获取前一个月或者下一个月的月份, 参数中 负数 代表 往前, 正数 代表 往后。

--上一个月

select to_char(add_months(trunc(sysdate),-1),'yyyymm') from dual;

--下一个月

select to_char(add_months(trunc(sysdate),1),'yyyymm') from dual;

d. 观察自动创建的分区:

SQL> select table_name,partition_name from user_tab_partitions where table_name='INTERVAL_ANDY7';

TABLE_NAME                     PARTITION_NAME

------------------------------ ------------------------------

INTERVAL_ANDY7                 PART1

INTERVAL_ANDY7                 PART2

INTERVAL_ANDY7                 SYS_P24

INTERVAL_ANDY7                 SYS_P25

INTERVAL_ANDY7                 SYS_P26

INTERVAL_ANDY7                 SYS_P27

INTERVAL_ANDY7                 SYS_P28

INTERVAL_ANDY7                 SYS_P29

INTERVAL_ANDY7                 SYS_P30

INTERVAL_ANDY7                 SYS_P31

INTERVAL_ANDY7                 SYS_P32

TABLE_NAME                     PARTITION_NAME

------------------------------ ------------------------------

INTERVAL_ANDY7                 SYS_P33

INTERVAL_ANDY7                 SYS_P34

13 rows selected.

下面创建一个以天为间隔的分区表:

1. 创建分区表:

SQL> create table interval_andy8

2  (

3  id    number,

4  dt    date

5  )

6  partition by range (dt)

7  INTERVAL (NUMTODSINTERVAL(1,'day'))

8  (

9  partition p20141101 values less than (to_date('2014-11-1','yyyy-mm-dd'))

10  );

Table created.

2. 查看表分区:

SQL> select table_name,partition_name from user_tab_partitions where table_name='INTERVAL_ANDY8';

TABLE_NAME                     PARTITION_NAME

------------------------------ ------------------------------

INTERVAL_ANDY8                 P20141101

3. 插入测试数据:

begin

for i in 1 .. 12 loop

insert into INTERVAL_ANDY8 values(i,trunc(to_date('2014-11-1','yyyy-mm-dd')+i));

end loop;

commit;

end;

/

PL/SQL 过程已成功完成。

4. 观察自动创建的分区:

SQL> select table_name,partition_name from user_tab_partitions where table_name='INTERVAL_ANDY8';

TABLE_NAME                     PARTITION_NAME

------------------------------ ------------------------------

INTERVAL_ANDY8                 P20141101

INTERVAL_ANDY8                 SYS_P35

INTERVAL_ANDY8                 SYS_P36

INTERVAL_ANDY8                 SYS_P37

INTERVAL_ANDY8                 SYS_P38

INTERVAL_ANDY8                 SYS_P39

INTERVAL_ANDY8                 SYS_P40

INTERVAL_ANDY8                 SYS_P41

INTERVAL_ANDY8                 SYS_P42

INTERVAL_ANDY8                 SYS_P43

INTERVAL_ANDY8                 SYS_P44

TABLE_NAME                     PARTITION_NAME

------------------------------ ------------------------------

INTERVAL_ANDY8                 SYS_P45

INTERVAL_ANDY8                 SYS_P46

13 rows selected.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值