2011-01-24 54 views
2

我有奇怪的Oracle优化器行为:甲骨文:全扫描,而不是使用综合指数

SELECT a.id, 
     a.date_insert, 
     a.message#cnt 
    FROM T_MESSAGE_TRANSMIT A, 
     T_LIST l 
WHERE a.priority_id = 0 
    AND a.status = 'Q' 
    and l.id = a.list_id 

此查询过T_MESSAGE_TRANSMIT生产全扫描,不管事实,这是一个索引覆盖priority_idstatus领域:

CREATE BITMAP INDEX INFORMER.IX$MESSAGE_TRANSMIT$6 ON INFORMER.T_MESSAGE_TRANSMIT (STATUS, PRIORITY_ID) 

表格大小约为28M行,它已在7天前进行了分析(从那天起仅添加了数千行)。

如果我使用提示/*+index(a IX$MESSAGE_TRANSMIT$6) */那么一切都变好,还有如果我删除加入,并重写查询:

SELECT a.id, 
     a.date_insert, 
     a.message#cnt 
    FROM T_MESSAGE_TRANSMIT A, 
WHERE a.priority_id = 0 
    AND a.status = 'Q' 

如果我能出错?

UPD

的问题是在这个优化设置:

optimizer_mode first_rows_10 
+0

更新了统计数据? – 2011-01-24 04:12:05

+0

@OMG小马:统计数据已于7天前更新。 – zerkms 2011-01-24 04:14:49

回答

3

什么行的比例相匹配的优先级ID /状态标准是什么?

例如,如果有20%的行匹配,那么它将不得不在20%的情况下访问该行以获取额外的细节。如果它正在访问20%的行,它可能会访问80-90%的块。在这种情况下,忽略索引是正确的。

但是,如果它在没有联接的情况下使用查询的索引,则更可能是由于a.list_id值。如果它使用BITMAP索引,那么它对于在其中找到的每一行都必须通过id访问T_LIST表。如果T_LIST很大并且id没有编入索引,那么这可能意味着重复对T_LIST的完整扫描是一个坏主意。

在这种情况下,它可能会从T_MESSAGE_TRANSMIT获取所有匹配的行,按ID对它们进行排序,然后从T_LIST中获取匹配的行。对T_LIST的散列连接也可能是合适的。

而且,你一定要做到并不简单想做

SELECT a.id, 
     a.date_insert, 
     a.message#cnt 
    FROM T_MESSAGE_TRANSMIT A 
WHERE a.priority_id = 0 
    AND a.status = 'Q' 
    AND a.list_id in (select l.id from T_LIST l) 

如果ID是不T_LIST独特,原始的SQL会产生重复。