【发布时间】:2011-04-27 13:56:19
【问题描述】:
这是Strategy to improve Oracle DELETE performance 的后续问题。回顾一下,我们有一个大型数据库,其中包含代表优化系统的 1D 到 4D 输出数据的表层次结构。读取和写入这些数据的速度很快,并且为我们的各种系统利用这些信息提供了一种便捷的方式。
但是,删除未使用的数据已成为一种负担。当前表层次结构如下。
/* Metadata tables */
Case(CaseId, DeleteFlag, ...) On Delete Cascade CaseId
OptimizationRun(OptId, CaseId, ...) On Delete Cascade OptId
OptimizationStep(StepId, OptId, ...) On Delete Cascade StepId
/* Data tables */
Files(FileId, CaseId, Blob) /* deletes are near instantateous here */
/* Data per run */
OnedDataX(OptId, ...)
TwoDDataY1(OptId, ...) /* packed representation of a 1D slice */
/* Data not only per run, but per step */
TwoDDataY2(StepId, ...) /* packed representation of a 1D slice */
ThreeDDataZ(StepId, ...) /* packed representation of a 2D slice */
FourDDataZ(StepId, ...) /* packed representation of a 3D slice */
/* ... About 10 or so of these tables exist */
我正在寻找一种对Case 数据进行分区的方法,以便我可以删除与案例相关的分区以删除其数据。理想情况下,OptimizationRun 将有一个基于CaseId 的间隔分区,这将过滤到其子级。但是,11g 不支持 INTERVAL 和 REF 分区的组合。
根据数据库大小和表空间位于 ASSM 中的要求,我相当肯定 ENABLE ROW MOVEMENT 是不可能的。也许OptimizationRun 上的RANGE 分区和其余部分上的REF 分区?
我的猜测是使用该策略,我需要一个触发器来完成以下操作:
CREATE OR REPLACE TRIGGER Case_BeforeInsert_MakePartitions
BEFORE INSERT
ON Case
FOR EACH ROW
DECLARE
v_PartName varchar(64) := 'CASE_OPTPART_' || :new.CaseId;
v_PartRange Case.CaseId%type := :new.CaseId
BEGIN
-- Take :new.CaseId and create the partition
ALTER TABLE OptimizationRun
ADD PARTITION v_PartName
VALUES LESS THAN ( v_PartRange );
END;
然后是删除前的必要触发器:
CREATE OR REPLACE TRIGGER Case_BeforeDelete_RemovePartitions
BEFORE DELETE
ON Case
FOR EACH ROW
DECLARE
v_PartName varchar(64) := 'CASE_OPTPART_' || :old.CaseId;
BEGIN
-- Drop the partitions associated with the case
ALTER TABLE OptimizationRun
DROP PARTITION v_PartName;
END;
好主意?或者这是 SNL Bad Idea Jeans 广告中的创意?
更新,供尺寸参考:
- 一维数据表~1.7G
- 2D 数据表 ~12.5G
- 3D 数据表 ~117.3G
- 4D 数据表 ~315.2G
【问题讨论】:
-
如何标记删除? (它背后的逻辑是什么)。也许基于日期? (老化记录)。还有什么?这可能有助于得出最佳方法
-
DeleteFlag由用户设置,这会导致触发器应用DeleteDate或SYSDATE + 14,以防用户想要撤消他们的决定。