我们有两个这样的表:
Event
id
type
... a bunch of other columns
ProcessedEvent
event_id
process
有定义的索引
- 事件(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 索引进行全索引扫描
- 对事件索引进行全索引扫描
- 事件表上的表访问
- 过滤事件表
- 两组之间的反连接
恕我直言,这真的很愚蠢。
所以我的问题是:oracle 坚持提前访问表的原因可能是什么?
补充:性能很差。我们通过仅选择 Event.IDs 然后“手动”获取所需的行来解决性能问题。但这当然只是一种解决方法。