由于一卡通消费数据过多,不利于按时间统计计算,故采取建立分区表的方式来优化查询效率,建立过程如下

创建一卡通消费数据分区表,按时间进行分区,建立时可暂时只创建一个最早时间分区,后续分区通过存储过程自动创建。这里把一卡通消费表直接复制过来,由于操作时间在自动建立分区时不好处理,故修改为varchar类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
create table M_REC_CONSUME
(
ECODE VARCHAR2(20) default 00000000 not null,
ID NUMBER not null,
NOTECASE NUMBER,
CUSTOMERID NUMBER not null,
OUTID VARCHAR2(18) not null,
CARDSN NUMBER not null,
OPCOUNT NUMBER,
OPDT VARCHAR2(100) not null,
ODDFARE NUMBER not null,
OPFARE NUMBER not null,
MNGFARE NUMBER not null,
ACCCODE NUMBER not null,
DSCRP VARCHAR2(20) not null,
TERMID NUMBER not null,
RECNO NUMBER not null,
UPLOADDATE DATE not null,
SAMCARDNO NUMBER not null,
SAMTRADENO NUMBER not null,
TRADECARDTYPE NUMBER not null,
TAC NUMBER,
ASN VARCHAR2(20),
UPDATEFLAG VARCHAR2(20) not null,
UPDATEDT DATE default sysdate not null,
DOWNDT DATE,
SOURCETABLE NUMBER not null
)
partition by range (opdt)
(
partition p201201 values less than ('2012-02-01 00:00:00')

–创建分区以历史有效记录的第一个月开始,这里要注意分区条件为less than )

创建存储过程自动建立到当前月份的分区,并写入日志。 存储过程创建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
CREATE OR REPLACE PROCEDURE GENE_AUTO_ADD_PARTITION
IS
/***********************************************************************
/* Procedure : GENE_AUTO_ADD_PARTITION
/* Description : General类程序,用于自动增加分区表的分区 == 计算到part_month为止,该增加多少个分区
/* Logic : 1、找出需要增加分区的分区表,以及这些分区表的最近分区
/* 2、计算这些分区表要增加几个分区
/* 3、循环为这些分区表增加分区,直至增加到part_month分区为止
/* 4、记录日志
/* Warning : 确保有足够权限,需显示授权:Grant select on dba_segments to user;
/* eg : call gene_auto_add_partition;
/* Author YYYY-MM-DD DSC
/* lihan 2015-04-24 初始版本
/*
/*********************************************************************/
part_month varchar2(100);
vcurrPartitionName varchar2(100);
vhistPartitionName varchar2(100);
vCount number;
vDDLSql varchar2(1024);
vLessthan varchar2(100);
i1 number;
i2 number;
BEGIN
--初始化参数值
part_month :=to_char(sysdate + 90,'yyyymm');--可提前新建三个月后的分区,预留问题发现及修复时间
i1 :=0;
--format current partition name
vcurrPartitionName := 'p'||part_month;
For x in (
SELECT segment_name , max(partition_name) partition_name, max(tablespace_name) tablespace_name
FROM dba_segments a
WHERE owner = 'YBG_CP'
AND segment_type = 'TABLE PARTITION'
AND segment_name not like '%BIN%'
AND not exists (
SELECT 1 FROM dba_segments b
WHERE a.segment_name = b.segment_name
AND b.partition_name = vcurrPartitionName)
GROUP BY a.segment_name
) LOOP
--计算需要增加几个分区
SELECT (extract(year from to_date(part_month,'yyyymm')) - extract(year from to_date(substr(x.partition_name,2,6),'yyyymm')))*12 +
(extract(month from to_date(part_month,'yyyymm')) - extract(month from to_date(substr(x.partition_name,2,6),'yyyymm')))
INTO vCount
FROM dual;
For j in 1..vCount LOOP
--get history Partition name
vhistPartitionName := 'p'||to_char(add_months(to_date(substr(x.partition_name,2,6),'yyyymm'),j),'yyyymm');
vLessthan := to_char(add_months(to_date(substr(x.partition_name,2,6)||'01','yyyy-mm-dd hh24:mi:ss'),j+1),'yyyy-mm-dd hh24:mi:ss');
vDDLSql := 'ALTER TABLE M_REC_CONSUME ADD PARTITION '||vhistPartitionName||' VALUES LESS THAN ('''||vLessthan||''' ) TABLESPACE '||x.tablespace_name;
DBMS_UTILITY.exec_ddl_statement(vDDLSql);
i1:= i1 + 1;
END LOOP;
i1 := i1;
i2 := i2 + 1;
END LOOP;
insert into m_rec_consume_log(updtime,prc_name,dscp)values(sysdate,'GENE_AUTO_ADD_PARTITION','为M_REC_CONSUME创建三个月后子分区成功,共创建了'||i1||'个分区');
commit;
EXCEPTION
WHEN others THEN
raise;
rollback;
insert into m_rec_consume_log(updtime,prc_name,dscp)values(sysdate,'GENE_AUTO_ADD_PARTITION','更新分区失败!');
END;

还需创建一个日志表:

1
2
3
4
5
6
create table m_rec_consume_log
(
updtime date,
prc_name varchar2(1000),
dscp varchar2(1000)
)

设定job定时执行存储过程完成分区自动创建。