【问题标题】:Performance issue - will collections improve perf? [closed]性能问题 - 集合会提高性能吗? [关闭]
【发布时间】:2019-11-11 15:36:41
【问题描述】:

我有一个性能问题,也许你可以帮忙解决。当我打开游标时,我会运行其他几个 SELECT 语句来使用游标中的变量检索值(见下文)。这似乎减慢了整个过程;我认为这是因为 PL/SQL 和 SQL 引擎之间的切换。使用表格集合会有帮助吗?但正如我所见,由于我需要来自不同表的不同列,我需要有几个不同的集合,我如何在一条记录中输出所有内容以返回结果集?

CREATE OR REPLACE procedure sp_test (in_input in number)  
as 
  v_calc number;
  v_calc_res number;
  v1 number;
  v2 number;
  v3 number;
  CURSOR C_test IS 
    select col1 from test where col1 = in_input;
begin
  open c_test
  loop
    fetch c_test into v_calc;

    select col1 into v1 from t1;

    select col1 into v2 from t2;

    select col1 into v3 from t3;

    v_calc_res := v_calc * 5 * v1 * v2 * v3;

    dbms_output.put_line(v_calc_res);

  end loop;
end sp_test;
/

【问题讨论】:

  • 您可能觉得需要混淆您的查询,但不幸的是,所有 blah-blah-blah 都只是 meh。我们几乎无法为您提供建议。请阅读this answer on asking Oracle performance questions。它将解释您需要提供多少信息才能在此处获得满意的答案;它还可以指导您如何诊断(甚至可能解决)您自己的问题。
  • 您的示例(我对其进行了编辑以简化标识符名称)在循环中缺少退出条件;希望您的真实代码没有丢失?另外,循环内的选择语句与游标有何关系?最后,您如何确保循环中的选择最多返回一行?
  • 嗨 Boneist,是的,有退出条件(我只是给出了一个简单的例子,而不是实际的代码)。循环内的 Select 语句只是从 Where 子句中的光标中获取变量。

标签: oracle performance plsql query-optimization


【解决方案1】:

逐行通常是缓慢的。

如果可能的话,最快的方法是跳过循环并在单个SELECT 语句中执行所有操作,将所有涉及的表加入到操作中。这可能是一个巨大的查询,所以我建议你一步一步地添加一个表,检查性能,注意执行计划,所涉及的索引列以及其他任何可能有助于提高性能。

【讨论】:

  • 谢谢!但实际上,我最终会得到带有外部连接的大量查询——从调试的角度来看,如果一个特定的 SQL 没有返回,那就不是很好了。但这一定是一个普遍的问题。我确实想过有几个集合并将结果集更新为 GTT - 但我不知道这是否是最好的前进方式。
  • 不客气。我知道程序选项更容易维护(如果这个比那个,否则......),但是 - 正如您已经知道的那样 - 性能会受到影响。外连接不是邪恶,必要时使用它们。经常测试!收藏有什么好处吗?试试看;让我们知道结果。在我看来,一个select 应该是要走的路,但请随意做任何你认为合适的事情。也许您编写的代码不一定是最好的,但足够好。祝你好运!
【解决方案2】:

尝试在一次游标查询中使用所有内容。

以下是代码,它是尝试向您展示考虑到您的代码的演示。

CREATE OR REPLACE PROCEDURE SP_TEST (
    IN_INPUT IN   NUMBER
)  
as
    -- COMMENTED ALL THE VARIABLE EXCEPT NECESSARY ONE
    --V_CALC NUMBER;
    V_CALC_RES NUMBER;
    --V_BLAH_BLAH NUMBER;
    --V_BLAH_BLAH_BLAH NUMBER;
    --V_BLAH_BLAH_BLAH NUMBER;

CURSOR C_TEST IS 
SELECT --T.blah, T1.blah_blah, T2.blah_blah_blah , T3.blah_blah_blah_blah
    T.BLAH * 5 * T1.BLAH_BLAH * T2.BLAH_BLAH_BLAH * T3.BLAH_BLAH_BLAH_BLAH -- CALCULATION HERE
FROM
    TEST T -- ADDED ALL JOINS HERE
INNER JOIN T_BLAH_BLAH T1 ON (<JOIN CONDITION>)
      INNER JOIN t_blah_blah_blah T2 ON (<JOIN CONDITION>)
      INNER JOIN t_blah_blah_blah_blah T3 ON (<JOIN CONDITION>)
      where T.blah  = in_input;  -- WHERE CONDITION HERE
BEGIN 
OPEN C_TEST
LOOP
    FETCH C_TEST INTO V_CALC_RES; --RESULT OF THE CALCULATION DIRECTLY HERE


-- ALL SINGLE STATEMENTS ARE COMMENTED
--select blah_blah into v_blah_blah from t_blah_blah;
--select blah_blah_blah into v_blah_blah_blah from t_blah_blah_blah;
--select blah_blah_blah_blah into v_blah_blah_blah_blah from t_blah_blah_blah_blah;


-- CALCULATION ALREADY DONE IN CURSOR
--v_calc_res := v_calc*5*v_blah_blah*v_blah_blah_blah*v_blah_blah_blah_blah;
    DBMS_OUTPUT.PUTLINE(V_CALC_RES);
END LOOP;

END;
/

干杯!!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-12
    • 2014-06-06
    • 1970-01-01
    • 2011-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多