我有一张表,它有大约 1.8 亿条记录和 40 个索引。一个夜间程序,将数据加载到此表中,但由于某些业务条件,我们只能删除并将数据加载到此表中。nightly 程序将从源系统中带来新记录或对表中现有记录的更新。我们有有限的窗口,即大约 6 小时来完成从源系统中提取,执行业务转换并最终将数据加载到此目标表中,并准备好让用户在早上消费数据。我们面临的问题是从该表中删除需要很长时间,主要是由于表上有 40 个索引(平均每小时 70000 次删除)。我在互联网上进行了一些挖掘,并查看了以下选项
a)在删除前删除或禁用索引,然后重建索引:删除和加载数据后将数据加载到目标表的程序需要执行相当多的索引更新。由于表中数据量巨大,重建 1 个索引需要将近 1.5 小时。所以这种方法是不可行的,因为重建索引需要时间,而且我们必须为用户准备好数据的时间有限
b)使用批量删除:目前程序是根据rowid删除,一条一条删除记录如下
DELETE
FROM <table>
WHERE rowid = g_wpk_tab(ln_i);
g_wpk_tab 是包含要删除的 rowids 的集合,该集合通过 FOR ALL 循环读取,我每删除 50000 行进行一次中间提交。
AskTom 的汤姆在这里的讨论中说批量删除和逐行删除将花费几乎相同的时间
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:5033906925164
所以这也不是一个可行的选择
c)定期删除: AskTom 的 Tom 建议使用定期删除,甚至可能由于该表上的索引数量而需要很长时间
d) CTAS:这种方法是没有问题的,因为程序需要重新创建表,创建 40 个索引,然后继续更新,我上面提到的索引将至少需要 1.5 小时才能创建
如果您能给我提供任何其他建议,我将不胜感激。
更新:截至目前,我们决定采用https://stackoverflow.com/users/409172/jonearles建议的方法来存档而不是删除。方法是在表中添加一个标志,将要删除的记录标记为 DELETE,然后在白天运行一个 post delete 程序来删除记录。这将确保数据在正确的时间可供用户使用。由于用户通过 OBIEE 进行消费,我们计划在表格上设置内容级别过滤器以不查看存档列,这样用户就无需知道选择什么和忽略什么。