【问题标题】:Query is taking 4800x longer when run from C++ program than from SQL Plus从 C++ 程序运行的查询比从 SQL Plus 运行的时间长 4800 倍
【发布时间】:2011-11-29 19:49:11
【问题描述】:

我们遇到了一个无法解释的查询的严重问题。在 SQL-plus 或 TOAD 中,它在 1/2 秒内运行,但当通过分布式事务从 C++ 程序运行时,它需要 41 分钟。到本周为止,它已经从 C++ 代码运行了 10,000 次,都在一秒钟内完成。

数据库、代码或运行代码的 W2k 服务器没有任何变化。

从代码运行时,它的 db 文件顺序读取次数非常高,超过 1,000,000

当从 SQL 运行完全相同的语句加上 db 文件顺序读取为 8 时

同样的语句在通过代码和 DT 运行时比通过 sqlplus 运行的工作量多 100,000 倍。

我们执行了以下查询来查找正在读取的块 选择 p1“文件#”,p2“块#”,p3“类#” 从 v$session_wait WHERE event = 'db 文件顺序读取'

它们是查询中使用的表。它一遍又一遍地读取表格,但解释计划表明只应读取 8 个块

两张桌子的大小约为 10 gig

这是声明和解释计划

SELECT COUNT (*)
  FROM student st, testinstance ti
 WHERE st.dataset_id = :b2
   AND st.student_id = ti.student_id
   AND ti.testinstance_id > :b1
   AND NOT EXISTS (
          SELECT 1
            FROM programscoringexclusion ex
           WHERE ex.program_id = wfgeneral.getprogramid (:b3)
             AND ex.testfamily_id = ti.testfamily_id
             AND NVL (ex.test_level, NVL (ti.test_level, '*')) =
                                                      NVL (ti.test_level, '*')
             AND NVL (ex.battery, NVL (ti.battery, '*')) =
                                                         NVL (ti.battery, '*')
             AND NVL (ex.form, NVL (ti.form, '*')) = NVL (ti.form, '*'))

             Plan
SELECT STATEMENT  CHOOSECost: 2                     
    9 SORT AGGREGATE  Bytes: 43  Cardinality: 1                 
        8 FILTER            
            5 NESTED LOOPS  Cost: 2  Bytes: 43  Cardinality: 1          
                2 TABLE ACCESS BY INDEX ROWID TABLE BBOX.TESTINSTANCE Cost: 1  Bytes: 32  Cardinality: 1    
                    1 INDEX RANGE SCAN INDEX (UNIQUE) BBOX.XXPK0TESTINSTANCE Cost: 1  Cardinality: 1  
                4 TABLE ACCESS BY INDEX ROWID TABLE BBOX.STUDENT Cost: 1  Bytes: 11  Cardinality: 1     
                    3 INDEX UNIQUE SCAN INDEX (UNIQUE) BBOX.XXPK0STUDENT Cost: 1  Cardinality: 1  
            7 TABLE ACCESS BY INDEX ROWID TABLE BBOX.PROGRAMSCORINGEXCLUSION Cost: 1  Bytes: 37  Cardinality: 1         
                6 INDEX RANGE SCAN INDEX BBOX.XXIE1PROGRAMSCORINGEXCLUSION Cost: 1  Cardinality: 1  

当一个语句实际运行时,我们如何才能看到它的实际计划是什么?我们可以看出它正在阅读上面的表格。实际计划是否可能与我们看到的不同,实际上是在进行某种笛卡尔连接或一些需要 40 分钟才能解决的奇怪事情?有没有办法确定?

【问题讨论】:

    标签: oracle


    【解决方案1】:

    要找到实际使用的计划,您可以使用 sql_id 查询 v$sql_plan。最简单的做法是在查询中添加注释以使其唯一,例如

    select /* FROM C++ */ ....
    

    select /* FROM SQLPLUS */ ....
    

    然后运行查询。从 v$sql 查询可以找到查询的 SQL_ID,例如:

    select sql_id, sql_fulltext
    from v$sql
    where upper(sql_fulltext) like '%FROM C++%';
    

    然后使用该 SQL_ID,您可以查询 v$sql_plan 以获取计划,或者更好的是,使用以下查询:

    select * from table(dbms_xplan.diplay_cursor('SQL ID OBTAINED ABOVE'));
    

    【讨论】:

      猜你喜欢
      • 2023-03-10
      • 1970-01-01
      • 2017-09-10
      • 1970-01-01
      • 2012-09-02
      • 1970-01-01
      • 1970-01-01
      • 2016-09-29
      • 2021-09-21
      相关资源
      最近更新 更多