【问题标题】:Oracle optimizer using functions in sql statementsOracle 优化器在 sql 语句中使用函数
【发布时间】:2017-12-15 13:39:12
【问题描述】:

我有一个用 PL/SQL (Oracle 11.2g) 开发的外部 API,用于我的模块 SQL 语句。这是一个极其简化的例子:

select *
from (select column_value c from table(api_pkg.function(param1, param2))) t1
join table2 t2
  on t2.pkc = t1.c
...

其中 table2.pkc 是此类表的 PK。问题是优化器不使用table2索引,​​查询性能很低。

如果我创建一个表

create table tmp_result as 
select column_value c from table(api_pkg.function(param1, param2))

我在第一个查询中使用它,优化器使用 table2 索引

select *
from tmp_result t1
join table2 t2
  on t2.pkc = t1.c

而且性能很棒。可以合理地认为,由于 Oracle 不知道函数将返回的行数,因此无法正确优化查询。

原始查询连接了 23 个表,而我很少有其他表使用这种方法并具有良好的执行计划,因此我不愿意添加提示来强制执行正确的执行计划。相反,我可以强制优化器首先找出函数返回的行数,然后生成计划吗?或者,当然还有其他方法?

到目前为止,我尝试了http://www.dba-oracle.com/t_materialize_sql_hint.htm,但没有成功,也无法强制使用带有提示的特定索引。

【问题讨论】:

  • 您的函数通常可能返回多少行?它可能有很大的不同(即 1 行与 100 万行,具体取决于参数),还是大致相似?如果是后者,那么您可以考虑使用基数提示来说明预期的行数。它不必完全准确 - 例如,如果您返回 3000 行,则 1000 可能是一个足够好的“猜测”,但如果您期望 100 万行而您实际上得到 10 行,那么您可能不会得到最好的计划。
  • @Daniel Gutierrez - 您是否尝试在查询中使用索引提示? /*+ index(t2 t2_idex_name) */ 之类的东西...应该紧跟在 SELECT 关键字之后。
  • 您可以查看ASSOCIATE STATISTICS 将扩展统计信息应用于函数oracle-developer.net/display.php?id=426
  • 其实同站的这篇文章可能更适合你的场景:setting cardinality for pipelined and table functions
  • 是的,成本会随着动态采样而变化。所以呢?我从不看它。

标签: plsql oracle11g query-optimization


【解决方案1】:

也许尝试将此子查询移至with 子句。它可能会有所帮助。

如果您不想要 ORDEREDINDEX 之类的提示,则可能很难强制优化器对其进行计数,除非您先将结果插入临时表。

【讨论】:

    猜你喜欢
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    相关资源
    最近更新 更多