我有一个名为 MyTable 的事件表,在此表中我有MyTableId列,我们在其上创建了索引。该表有7000万行。 现在,我创建了一个清除过程,它根据表类型集合 MyTableCollection 清除事件。该集合有100行限制。因此,作为一个整体,我们可以一次清除100行。但是当我在proc中运行下面的查询时,它被卡住了40分钟。
DELETE FROM MyTable
WHERE MyTableId IN (SELECT MyTableId FROM TABLE(MyTableCollection))
当我使用硬编码值在此查询上运行分析器时,它显示了索引范围扫描
DELETE FROM MyTable
WHERE MyTableId IN (10,20,30)
在幕后查询中的集合是否扮演了在查询中不使用索引的角色?我在想oracle可能会对集合中提取的行数感到困惑。我对么 ?溶液
P.S:我正在考虑实施FORALL来删除行。
答案 0 :(得分:1)
执行此操作时......
WHERE MyTableId IN (10,20,30)
...优化器足够聪明,知道它会打三行。但如果你这样做......
WHERE MyTableId IN (SELECT /*+ CARDINALITY(MyTableCollection 3) */MyTableId FROM TABLE(MyTableCollection))
然后它不知道集合中有多少行。因此它假定有8192行,并相应地选择执行计划。
但是你可以使用cardinality
提示告诉优化器集合中有多少行:
WHERE MyTableId IN (SELECT /*+ CARDINALITY(MyTableCollection 100) */
MyTableId FROM TABLE(MyTableCollection))
“此表有7000万行”
顺便说一下,检查表统计信息的新鲜度是值得的,因为我们仍然希望优化器考虑索引来获得8192/70000000行。