Esta es una pregunta de seguimiento a Strategy to improve Oracle DELETE performance. Para recapitular, tenemos una gran base de datos con una jerarquía de tablas que representan los datos de salida 1D a 4D de un sistema de optimización. Leer y escribir esta información es rápido y proporciona un medio conveniente para que nuestros diversos sistemas utilicen la información.Solución de particionamiento de Oracle para DELETE problema de rendimiento
Sin embargo, eliminar los datos no utilizados se ha convertido en un oso. La jerarquía de la tabla actual está debajo.
/* 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 */
Lo que estoy buscando es un medio de dividir los datos Case
tal que podía caer una partición en relación con el caso para eliminar sus datos. Idealmente, OptimizationRun
tendría una partición de intervalo basada en CaseId
y esto se filtraría a través de sus hijos. Sin embargo, 11g no admite la combinación de particiones INTERVAL y REF.
Estoy bastante seguro de que ENABLE ROW MOVEMENT está fuera de cuestión en función del tamaño de la base de datos y el requisito de que los espacios de tabla vivan en ASSM. Tal vez RANGE partición en OptimizationRun
y particionamiento REF en el resto?
Mi conjetura es que la estrategia con la que iba a necesitar un disparador que logra algo como lo siguiente:
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;
Y luego el gatillo requisito para antes de la eliminación:
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;
Buena idea? ¿O es esta una idea del comercial de SNL Bad Idea Jeans?
actualización, para referencia del tamaño:
- tablas de datos 1D ~ 1,7 g
- tablas de datos 2D ~ 12,5 g
- tablas de datos 3D ~ 117.3G
- tablas de datos 4D ~ 315,2 G
cómo se marcan las eliminaciones? (cuál es la lógica detrás de esto). ¿Basado en una fecha tal vez? (envejecimiento de los registros). ¿Algo más?Esto puede ayudar a obtener el mejor enfoque – tbone
'DeleteFlag' es establecido por el usuario, lo que hace que un disparador aplique un' DeleteDate' de 'SYSDATE + 14', en caso de que el usuario desee deshacer su decisión. – user7116