Oracle 反联接执行计划问题

标签: Oracle
发布时间: 2014/3/1 22:18:18
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.

我们有两个表就像这样:

Event
    id
    type
    ... a bunch of other columns

ProcessedEvent
    event_id
    process

有为定义的索引

  • Event(id) (PK)
  • ProcessedEvent (event_id,进程)

第一个表示应用程序中的事件。

第二个表示某一事件有进程由某一过程的事实。有很多需要处理某一事件,因此,在第一的每个条目的第二个表中有多个条目的过程。

为了找到那需要处理的所有事件,我们执行以下查询:

select * // of course we do name the columns in the production code
from Event
where type in ( 'typeA', 'typeB', 'typeC')
and id not in (
    select event_id
    from ProcessedEvent
    where process = :1  
)

是最新的统计数字

由于大多数事件进行处理,我认为最佳的执行计划应该看这样的事情

  • ProcessedEvent 指数全索引扫描
  • 关于事件索引全文索引扫描
  • 反两个之间的联接
  • 与其他表访问
  • 筛选器

相反,Oracle 会执行下列

  • ProcessedEvent 指数全索引扫描
  • 关于事件表的全表扫描
  • 筛选事件表
  • 反的两个集之间的联接

使用索引提示我可以获得 Oracle 进行以下操作:

  • ProcessedEvent 指数全索引扫描
  • 关于事件索引全文索引扫描
  • 关于事件表表 acces
  • 筛选事件表
  • 反的两个集之间的联接

这是真的很蠢很宽。

所以我的问题是: oracle 坚持早期表访问的原因可能是什么?


加法: 性能是坏的。通过选择只是 Event.IDs,然后获取所需的行 '手动',我们正在修复性能问题。但当然这是只是在附近的工作。

解决方法 1:

您完全索引扫描可能会比全表扫描更快因为索引很可能会比表的"更薄"。仍然,完全索引扫描是完整段阅读,它将是同样的成本作为全表扫描。

然而,您还可以添加表 ROWID 访问所迈出的一步。这是一个昂贵的步骤: 一个逻辑 IO每行的 ROWID 访问而你能得到一个逻辑 IO每多块(取决于您 db_file_multiblock_read_count parameter ) 为全表扫描。

总之,优化程序会计算的:

cost(FULL TABLE SCAN) < cost(FULL INDEX SCAN) + cost(TABLE ACCESS BY ROWID)

更新: 全表扫描还可以上类型的筛选器比全索引扫描路径 (因为索引并不知道是什么事件的类型),因此早减少将反联接结果集的大小 (另一个优势的全表扫描)。

官方微信
官方QQ群
31647020