Oracle查询计划效率问题

Leo*_*nid 5 sql oracle plsql

以下查询在a中给出PL/SQL procedure.

SELECT e.data FROM extra e WHERE e.external_id in
    (SELECT * FROM TABLE (p_external_ids)).
Run Code Online (Sandbox Code Playgroud)

类型p_external_idscreate or replace type "VARCHAR2TABLE" as table of VARCHAR2(4000 CHAR).

Oracle使用全表扫描无效地执行查询.查询提示没有帮助,必要的索引到位.当表中的行数为200 000时,SELECT *使用硬编码ID 替换部件会将查询运行时间减少a .factor of 20

作为参考,执行with 子句需要大约0.3秒SELECT * FROM TABLE,并且0.015 ms对于单个硬编码的id 需要大约0.3秒.

有哪些建议的有效方法(密钥搜索)来编写存储过程以从表中提取多个ID的数据?必须使用提供的集合类型将id列表传递给存储过程.

Jus*_*ave 7

你尝试了什么提示?你能发布快速和慢速的查询计划吗?

在SQL中使用PL/SQL集合的一个普遍问题是,CBO经常猜测集合中的元素数量,并因此选择错误的计划.在这些情况下使用CARDINALITY提示通常很有帮助,即

SELECT e.data 
  FROM extra e
 WHERE e.external_id IN (
    SELECT /*+ cardinality(ids 10) */ *
      FROM TABLE( p_external_ids ) ids
  )
Run Code Online (Sandbox Code Playgroud)

告诉优化器期望P_EXTERNAL_IDS中有10个元素.

Tom Kyte还对askTom上的基数提示和PL/SQL集合进行了更深入的讨论.

EXTERNAL_ID列的数据类型是什么?您的集合是字符串的集合,但EXTERNAL_ID往往意味着NUMBER.这里真的存在数据类型不匹配的问题吗?

如果问题是优化器在引用集合时无法获得准确的基数估计值,那么将集合复制到临时表中只会有所帮助,但是当您引用临时表时,它可以获得准确的估计值.如果您正确指定CARDINALITY提示并且不会改变性能,那么这意味着问题不在于优化程序的基数估计值.

你可以发布快速和慢速的查询计划吗?你能发布你正在使用的包含CARDINALITY提示的确切SQL语句(可能存在语法错误)