Oracle:使用fullscan而不是复合索引

时间:2011-01-24 04:07:56

标签: oracle indexing

我有奇怪的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

1 个答案:

答案 0 :(得分: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将生成重复项。