我有以下查询:
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_mxsequities
。
quotes_mxsequities
正在使用索引
instruments
正在进行全表扫描
答案 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;