提高Oracle DELETE性能的策略

use*_*116 15 oracle oracle11g

我们的Oracle 11g安装开始变得越来越大.此数据库是在群集上运行的并行优化系统的后端.过程的输入包含在数据库中,同时包含优化步骤的输出.输入包括死记硬背配置数据和一些二进制文件(使用11g的SecureFiles).输出包括当前存储在DB中的1D,2D,3D和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 */
Run Code Online (Sandbox Code Playgroud)

一个收割者的脚本每天都会出现并查找案例DeleteFlag = 1并继续使用DELETE FROM Case WHERE DeleteFlag = 1,允许级联继续.

这种策略非常适合读/写,但是当我们想要清除数据时,它现在超出了我们的能力!摩擦是删除一个案例需要大约20-40分钟,具体取决于大小,并经常超载我们的归档空间.该产品的下一个主要版本将采用"从头开始"的方法来解决问题.下一个次要版本需要保持在数据库中存储的数据范围内.

因此,对于次要版本,我们需要一种可以提高删除性能的方法,并且最多需要对数据库进行适度的更改.

  1. REF分区,但问题是如何?我很乐意Case在其他地方进行INTERVAL 和REF,但这不受支持.是否有某种方式来手动分区OptimizationRunCaseId通过触发器?
  2. 禁用存档/重做日志以进行删除?无法找到与此相关的提示.不确定它是否可行.
  3. 截短?这可能需要一些复杂的表设置.但也许我没有考虑我所有的选择. (每个答案,受到打击)

为了帮助说明这个问题,每个案例的数据范围从15MiB到1.5GiB,从20k到2M行.

更新: DB的当前大小约为1.5TB.

ik_*_*elf 7

对于数据库来说,删除数据是一项艰巨的工作.它必须在映像之前创建,更新索引,写入重做日志并删除数据.这是一个缓慢的过程.如果您可以有一个窗口来执行此任务,那么最简单,最快捷的方法是构建包含所需数据的新表.删除旧表并重命名新表.这需要一些设置工作,这是显而易见的,但很有可能.不那么激烈的一步是在删除发生之前删除索引.我的投票将用于CTAS(Create Table As Select from)并构建新表.一个好的分区模式肯定会有所帮助,也许在下一个版本中Oracle可以组合间隔和引用分区.拥有它会非常好.

禁用日志记录....不能删除,但CTAS可以使用nologging.准备好后进行备份,并确保将数据文件传输到备用数据库(如果有).