使用Table函数查询不使用索引

时间:2016-07-29 07:47:33

标签: sql oracle performance oracle12c

我有以下查询:

select i.pkey as instrument_pkey,
       p.asof,
       p.price,
       p.lastprice as lastprice,
       p.settlementprice as settlement_price,
       p.snaptime,
       p.owner as source_id,
       i.type as instrument_type
from quotes_mxsequities p,
     instruments i,
     (select instrument, maxbackdays
      from TABLE(cast (:H_ARRAY as R_TAB))) lbd
where p.asof between :ASOF - lbd.maxbackdays and :ASOF
  and p.instrument = lbd.instrument
  and p.owner = :SOURCE_ID
  and p.instrument = i.pkey

由于我已经开始使用表函数,因此查询已经开始在表quotes_mxsequities上进行全表扫描。这是一个大表。

早些时候,当我使用IN子句时,正在使用表函数索引。

有关如何强制执行索引使用的任何建议吗?

编辑:

我会尝试获得解释计划,但只是要添加,H_ARRAY预计会有大约10,000个条目。 quotes_mxsequities是一张数百万行的大表。仪器又是一个大表,但行数小于quotes_mxsequitiesquotes_mxsequities正在使用索引

时,instruments正在进行全表扫描

2 个答案:

答案 0 :(得分:1)

很难回答没有关于表格结构,行数等的解释计划和信息。

作为一种通用的简化方法,您可以尝试强制使用INDEX hint的索引。

您的问题甚至可能是由于表处理中的错误顺序造成的;您可以尝试使用LEADING hint使Oracle遵循正确的顺序(我首先假设为LBD

另一点可能是完全访问,而你可能需要一个NESTED LOOP;在这种情况下,您可以尝试USE_NL hint

答案 1 :(得分:1)

很难确定所提供的有限信息的形式,但看起来这是优化者无法建立表集合表达式的基数的问题,因为其内容在解析时是未知的。使用存储的嵌套表,统计信息将可用,但此处没有可供使用的数据。

如果没有该信息,优化器默认猜测您的表集合将具有8K条目,并将其用作基数估计值;如果这是quotes_mxsequities中行数的很大一部分,那么它将决定索引不会有效,并将使用全表扫描。

您可以使用undocumented cardinality hint告诉优化器大致在集合中实际期望的元素数量;你可能不会确切知道,但你可能知道你通常期望在10左右。所以你可以添加一个提示:

select /*+ CARDINALITY(lbd, 10) */ i.pkey as instrument_pkey,

您也可以在这里找到有用的动态采样提示,但如果没有真实数据可查看,基数提示适用于基本执行计划,因此很容易看到它的效果。

顺便说一句,你不需要在表表达式上使用子查询,你可以稍微简化为:

from TABLE(cast (:H_ARRAY as R_TAB)) lbd,
     quotes_mxsequities p,
     instruments i

甚至更好地使用现代连接语法:

select /*+ CARDINALITY(lbd, 10) */ i.pkey as instrument_pkey,
       p.asof,
       p.price,
       p.lastprice as lastprice,
       p.settlementprice as settlement_price,
       p.snaptime,
       p.owner as source_id,
       i.type as instrument_type
from TABLE(cast (:H_ARRAY as R_TAB)) lbd
join quotes_mxsequities p
on p.asof between :ASOF - lbd.maxbackdays and :ASOF
  and p.instrument = lbd.instrument
join instruments i
on i.pkey = p.instrument
where p.owner = :SOURCE_ID;