【问题标题】:Most Efficient Version of PLSQL Stored ProcedurePLSQL存储过程的最高效版本
【发布时间】:2013-09-20 15:57:06
【问题描述】:

我正在编写一个 PL/SQL 存储过程,该过程将从 .NET 应用程序中调用。

我的存储过程必须返回

  • 部件修订表中的值计数,基于输入部件号,
  • 当前在此表中为输入部件号捕获的最低修订级别的名称
  • 数据库中与此部件号关联的特定单元的修订级别名称和输入单元 ID。

    单元的修订级别名称在单独的表中捕获,与部件修订表没有直接关系。

相关数据结构:

Table Part has columns:
    Part_ID int PK
    Part_Number varchar2(30)

Table Part_Revisions:
    Revision_ID int PK
    Revision_Name varchar2(100)
    Revision_Level int
    Part_ID int FK

Table Unit:
    Unit_ID int PK
    Part_ID int FK

Table Unit_Revision:
    Unit_ID int PK
    Revision_Name varchar2(100)

话虽如此,我将这三个数据元素查询到引用游标中以进行输出的最有效方法是什么?我正在考虑以下选项 1:

OPEN cursor o_Return_Cursor FOR
SELECT (SELECT COUNT (*)
          FROM Part_Revisions pr
          inner join PART pa on pa.part_id = pr.part_id
         WHERE PA.PART_NO = :1 )
          AS "Cnt_PN_Revisions",
       (select pr1.Revision_Name from Part_Revisions pr1 
            inner join PART pa1 on pa1.part_id = pr1.part_id
            WHERE PA.PART_NO = :1 and pr1.Revision_Level = 0)
          AS "Input_Revison_Level",
       (select ur.Revision_Name from Unit_Revision ur
            WHERE ur.Unit_ID = :2) as "Unit_Revision"
        FROM DUAL;

但是,Toad 的解释计划返回成本:2 基数:1,我怀疑这是因为我在主查询中使用了 DUAL。将其与选项 2 进行比较:

select pr.Revision_Name, (select count(*) 
                           from Part_Revisions pr1
                           where pr1.part_id = pr.part_id) as "Count",
                         (select ur.Revision_Name 
                           from Unit_Revision ur
                           where ur.Unit_ID = :2) as "Unit_Revision"
from Part_Revisions pr 
            inner join PART pa on pa.part_id = pr.part_id
            WHERE PA.PART_NO = :1 and pr.Revision_Level = 0

基本上我真的不知道如何比较我的执行计划的结果,以选择最佳设计。我还考虑了选项 1 的一个版本,我没有将两次加入 Part 表,而是将 Part_ID 选择到一个局部变量中,然后根据该值简单地查询 Part_Revisions 表。但是,这不是我可以使用解释计划来分析的。

【问题讨论】:

    标签: stored-procedures plsql sql-execution-plan


    【解决方案1】:

    您的描述和选择语句看起来不同...我的过程基于 SQL 语句。

    PROCEDURE the_proc
    (
        part_no_in         IN  NUMBER
    ,   revision_level_in  IN  NUMBER
    ,   unit_id_in         IN  NUMBER
    ,   part_rev_count_out OUT NUMBER
    ,   part_rev_name_out  OUT VARCHAR2
    ,   unit_rev_name_out  OUT VARCHAR2
    )
    AS
    BEGIN
        SELECT  COUNT(*)
        INTO    part_rev_count_out
        FROM    part  pa
        WHERE   pa.part_no = part_no_in
        AND     EXISTS
                (
                    SELECT  1
                    FROM    part_revisions  pr
                    WHERE   pa.part_id = pr.part_id
                );
    
        SELECT  pr1.revision_name 
        INTO    part_rev_name_out
        FROM    part_revisions  pr1
        WHERE   pr1.revision_level = revision_level_in
        AND     EXISTS
                (
                    SELECT  1
                    FROM    part  pa1
                    WHERE   pa1.part_id = pr1.part_id
                    AND     pa.part_no = part_no_in
                );
    
        SELECT  ur.revision_name
        INTO    unit_rev_name_out
        FROM    unit_revision ur
        WHERE   ur.unit_id = unit_id_in;
    END the_proc;
    

    【讨论】:

      【解决方案2】:

      看起来您正在获取标量值。与其返回游标,不如使用干净的 sql 语句返回值。我在 .net 上做了很多次,效果很好。

      Procedure get_part_info(p_partnum in part.part_number%type
          , ret_count          out integer 
          , ret_revision_level out part_revisions.revision_level%type
          , ret_revision_name  out part_revisions.revision_name%type) as
      begin 
         select count(*) into ret_count from ....;
         select min(revision_level) into ret_revision_level from ...;
         select revision_name in ret_revision_name...;
         return;
      end;
      

      【讨论】:

        猜你喜欢
        • 2011-01-24
        • 2015-04-01
        • 1970-01-01
        • 2022-10-22
        • 2018-10-13
        • 2018-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多