英文:
How can i set partition p2 to store only letest 3 months data in it?
问题
In this create partition part of the code block, 如何设置分区2仅存储最近3个月的数据在分区p2中?
英文:
In this create partition part of code block, how can i set partition 2 to store 3 months latest data within the partition p2 only?
CREATE TABLE server1.test_temp
PARTITION BY RANGE (receiveddate)
(
PARTITION P2_test_temp VALUES LESS THAN (TO_DATE('08-05-23', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
)
AS
SELECT * FROM server1.test;
答案1
得分: 1
请使用INTERVAL
分区,这会让您的生活变得更容易,例如像这样:
CREATE TABLE server1.test_temp
PARTITION BY INTERVAL (INTERVAL '3' MONTH)
(
PARTITION P_INITIAL VALUES LESS THAN (TIMESTAMP '2008-01-01 00:00:00')
)
英文:
Better use INTERVAL
partition, it makes your life much easier, for example like this:
CREATE TABLE server1.test_temp
PARTITION BY INTERVAL (INTERVAL '3' MONTH)
(
PARTITION P_INITIAL VALUES LESS THAN (TIMESTAMP '2008-01-01 00:00:00')
)
答案2
得分: 1
以下是您提供的内容的中文翻译:
最简单的解决方案是指定分区间隔,动态分配新日期指定大小的新分区。分区修剪 在where
条件、子查询甚至允许基于条件动态选择分区。
但是,如果由于某种原因,您仍然需要为过去三个月保留单个分区,并具有动态上边界,您需要安排每日作业,以相应地调整现有分区。它应该执行以下操作:
- 为新日期添加新分区,以使用其上边界作为新的上边界。
- 将此新分区合并到“旧”的最后一个分区中。
- 将最后一个分区在日期前的3个月拆分,以从最新分区中删除旧数据。
- 将此旧数据与以前的分区合并。否则,它将保留此一天的数据在其自己的分区中,最好考虑每日自动间隔分区。
以下是执行此特定表的步骤的过程。如果要将表作为参数传递,您需要进行调整并添加名称验证。
表和初始数据:
create table test_temp (
somedata varchar2(100),
receiveddate date
)
partition by range(receiveddate) (
partition p_2022 values less than(date '2023-01-01'),
partition p_2023 values less than(date '2023-02-08'),
partition p_last_3_month values less than (date '2023-05-08')
);
select *
from test_temp
partition (p_last_3_month)
SOMEDATA | RECEIVEDDATE |
---|---|
qwe | 2023-05-01 |
asd | 2023-02-09 |
create procedure p_keep_3_month_part(
p_date in date default trunc(sysdate)
)
as
tmp_partition_name constant varchar2(30) := 'TEMP_PARTITION';
last_partition_expr long;
last_partition_name varchar2(30);
prev_partition_name varchar2(30);
last_partition_date date;
/*Dynamic statement logging*/
procedure execute_immediate(l_stmt in varchar2)
as
begin
dbms_output.put_line(l_stmt);
execute immediate l_stmt;
end;
/*Merge partitions into the lower boundary partition name*/
procedure merge_partitions_to_lower(p_from in varchar2, p_to in varchar2)
as
begin
execute_immediate('alter table test_temp merge partitions ' ||
p_from || ' to ' || p_to ||
' into partition ' || p_to);
execute_immediate('alter table test_temp rename partition ' ||
p_to || ' to ' || p_from);
end;
begin
/*获取最后一个分区和上一个分区的信息以进行合并*/
select
partition_name,
lag(partition_name) over(partition by table_name order by partition_position asc)
into
last_partition_name,
prev_partition_name
from user_tab_partitions
where table_name = 'TEST_TEMP'
order by partition_position desc
fetch first row only;
/*为新日期添加新分区*/
execute_immediate('alter table test_temp add partition ' || tmp_partition_name ||
' values less than (date ''' || to_char(p_date, 'yyyy-mm-dd') || ''')');
/*将最后一个分区扩展到此新日期*/
merge_partitions_to_lower(last_partition_name, tmp_partition_name);
/*从最后一个分区中拆分旧数据*/
execute_immediate('alter table test_temp split partition ' || last_partition_name ||
' at (date ''' || to_char(add_months(p_date, -3), 'yyyy-mm-dd') ||
''') into (partition ' || tmp_partition_name || ', partition ' || last_partition_name || ')');
/*将旧数据与上一个分区合并*/
merge_partitions_to_lower(prev_partition_name, tmp_partition_name);
end;/
在2023-05-14
(截至今天的日期)拆分:
begin
dbms_output.put_line('');
p_keep_3_month_part(sysdate + 4);
end;/
1 行受影响
dbms_output:
alter table test_temp add partition TEMP_PARTITION values less than (date '2023-05-14')
alter table test_temp merge partitions P_LAST_3_MONTH to TEMP_PARTITION into partition TEMP_PARTITION
alter table test_temp rename partition TEMP_PARTITION to P_LAST_3_MONTH
alter table test_temp split partition P_LAST_3_MONTH at (date '2023-02-14') into (partition TEMP_PARTITION, partition P_LAST_3_MONTH)
alter table test_temp merge partitions P_2023 to TEMP_PARTITION into partition TEMP_PARTITION
alter table test_temp rename partition TEMP_PARTITION to P_2023
检查结果:
select table_name, partition_name, high_value, partition_position
from user_tab_partitions
TABLE_NAME | PARTITION_NAME | HIGH_VALUE | PARTITION_POSITION |
---|---|---|---|
TEST_TEMP | P_2022 | TO_DATE(' 2023-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') | 1 |
TEST_TEMP | P_2023 | TO_DATE(' 2023-02-14 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') | 2 |
TEST_TEMP | P_LAST_3_MONTH | TO_DATE(' 2023-05-14 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') | 3 |
select *
from test_temp
partition (p_last_3_month)
SOMEDATA | RECEIVEDDATE |
---|---|
qwe | 2023-05-01 |
英文:
The easiest solution would be to specify interval partitioning that will dynamically allocate new partitions of specified size for new dates. Partition pruning works very well with where
conditions and even subqueries and alows dynamic partition selection based on conditions.
However if, for some reason, you still need to have single partition for the last three month with dynamic upper boundary, you need to schedule daily job that will adjust existing partitions accordingly. It should:
- Add new partition for a new date to use its upper boundary as new upper boundary.
- Merge this new partition with the "old" last partition.
- Split the last partition at the 3 month before the date to remove old data from the latest partition.
- Merge this old data with the previous partition. Otherwise it will leave this one-day data in its own partition and it would be better to consider automatic interval partitioning on daily basis instead.
Below is the procedure that does these steps for this particular table. You need to adjust it and add name validations if you want to pass a table as a parameter.
Table and initial data:
create table test_temp (
somedata varchar2(100),
receiveddate date
)
partition by range(receiveddate) (
partition p_2022 values less than(date '2023-01-01'),
partition p_2023 values less than(date '2023-02-08'),
partition p_last_3_month values less than (date '2023-05-08')
);
select *
from test_temp
partition (p_last_3_month)
SOMEDATA | RECEIVEDDATE |
---|---|
qwe | 2023-05-01 |
asd | 2023-02-09 |
create procedure p_keep_3_month_part(
p_date in date default trunc(sysdate)
)
as
tmp_partition_name constant varchar2(30) := 'TEMP_PARTITION';
last_partition_expr long;
last_partition_name varchar2(30);
prev_partition_name varchar2(30);
last_partition_date date;
/*Dynamic statement logging*/
procedure execute_immediate(l_stmt in varchar2)
as
begin
dbms_output.put_line(l_stmt);
execute immediate l_stmt;
end;
/*Merge partitions into the lower boundary partition name*/
procedure merge_partitions_to_lower(p_from in varchar2, p_to in varchar2)
as
begin
execute_immediate('alter table test_temp merge partitions ' ||
p_from || ' to ' || p_to ||
' into partition ' || p_to);
execute_immediate('alter table test_temp rename partition ' ||
p_to || ' to ' || p_from);
end;
begin
/*get last and previous partition info for merge*/
select
partition_name,
lag(partition_name) over(partition by table_name order by partition_position asc)
into
last_partition_name,
prev_partition_name
from user_tab_partitions
where table_name = 'TEST_TEMP'
order by partition_position desc
fetch first row only;
/*Add new partition for new date*/
execute_immediate('alter table test_temp add partition ' || tmp_partition_name ||
' values less than (date ''' || to_char(p_date, 'yyyy-mm-dd') || ''')');
/*Extend last partition to this new date*/
merge_partitions_to_lower(last_partition_name, tmp_partition_name);
/*Split old data from the last partition*/
execute_immediate('alter table test_temp split partition ' || last_partition_name ||
' at (date ''' || to_char(add_months(p_date, -3), 'yyyy-mm-dd') ||
''') into (partition ' || tmp_partition_name || ', partition ' || last_partition_name || ')');
/*Merge old data with the previous partition*/
merge_partitions_to_lower(prev_partition_name, tmp_partition_name);
end;/
Split at 2023-05-14
(as of today's date):
begin
dbms_output.put_line('');
p_keep_3_month_part(sysdate + 4);
end;/
1 rows affected
dbms_output:
alter table test_temp add partition TEMP_PARTITION values less than (date '2023-05-14')
alter table test_temp merge partitions P_LAST_3_MONTH to TEMP_PARTITION into partition TEMP_PARTITION
alter table test_temp rename partition TEMP_PARTITION to P_LAST_3_MONTH
alter table test_temp split partition P_LAST_3_MONTH at (date '2023-02-14') into (partition TEMP_PARTITION, partition P_LAST_3_MONTH)
alter table test_temp merge partitions P_2023 to TEMP_PARTITION into partition TEMP_PARTITION
alter table test_temp rename partition TEMP_PARTITION to P_2023
Check the result:
select table_name, partition_name, high_value, partition_position
from user_tab_partitions
TABLE_NAME | PARTITION_NAME | HIGH_VALUE | PARTITION_POSITION |
---|---|---|---|
TEST_TEMP | P_2022 | TO_DATE(' 2023-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') | 1 |
TEST_TEMP | P_2023 | TO_DATE(' 2023-02-14 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') | 2 |
TEST_TEMP | P_LAST_3_MONTH | TO_DATE(' 2023-05-14 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') | 3 |
select *
from test_temp
partition (p_last_3_month)
SOMEDATA | RECEIVEDDATE |
---|---|
qwe | 2023-05-01 |
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论