繁体   English   中英

如何提高Oracle中动态SQL的查询性能

[英]How to improve query performance for dynamic sql in Oracle

我必须从运行时定义的表中获取数据,并基于运行时定义的列获取数据,我现在使用带有游标的动态sql,如下所示。 有没有更有效的方法来提高性能?

PROCEDURE check_error(p_table_name IN VARCHAR2
    ,p_keyword  IN VARCHAR2
    ,p_column_name IN VARCHAR2
    ,p_min_num IN NUMBER
    ,p_time_range IN NUMBER
    ,p_file_desc IN VARCHAR2
    )
IS  
   type t_crs is ref cursor;
   v_cur t_crs;

   v_file_name VARCHAR2(100);
   v_date_started DATE;
   v_date_completed DATE;
   v_counter NUMBER := 0;
   v_sql VARCHAR2(500);
   v_num NUMBER :=0;
BEGIN
   v_sql := 'SELECT '||p_column_name||', DATE_STARTED,DATE_COMPLETED FROM '||p_table_name
            || ' WHERE '||p_column_name||' LIKE '''||p_keyword||'%'' AND  DATE_STARTED > :TIME_LIMIT  ORDER BY '||p_column_name;

    OPEN v_cur FOR v_sql USING (sysdate - (p_time_range/1440));
    LOOP
        FETCH v_cur INTO v_file_name,v_date_started,v_date_completed;
        EXIT WHEN v_cur%NOTFOUND; 
        IF v_date_started IS NOT NULL AND v_date_completed IS NULL   
            AND (sysdate - v_date_started)*1440 > p_time_range THEN
                insert_record(co_alert_stuck,v_file_name,p_table_name,0,p_file_desc,p_time_range);               
        END IF;         
    END LOOP;
END;

顺便说一句,这会更好吗?

v_sql := 'SELECT :COLUMN_NAME1, DATE_STARTED,DATE_COMPLETED FROM :TABLE WHERE :COLUMN_NAME2 LIKE :KEYWORD AND  DATE_STARTED > :TIME_LIMIT  ORDER BY :COLUMN_NAME3';

OPEN v_cur FOR v_sql USING p_column_name,p_table_name,p_column_name,p_keyword||'%',(sysdate - (p_time_range/1440)),p_column_name;

首先,我不确定我是否了解代码在做什么。 在您发布的代码中(可能已简化为简化代码), IF语句检查v_date_started IS NOT NULL是否v_date_started IS NOT NULL ,这是多余的,因为DATE_STARTED上存在WHERE子句。 它检查(sysdate - v_date_started)*1440 > p_time_range是否只是DATE_STARTED列上WHERE子句的重复。 并且它检查v_date_completed IS NULL是否v_date_completed IS NULL ,这将在您构建的动态SQL语句中作为附加的WHERE子句更有效。 最好只在一个地方进行所有检查,而最有效的地方是在SQL语句中。

其次,该查询应返回多少行,时间花在哪里? 如果游标可能返回多行(许多的一些定义),你会得到一点效率,从做一个BULK COLLECT从光标到一个集合并修改insert_record程序来接受和处理的集合。 如果所有时间都花在执行SQL语句上,并且查询本身仅返回少量的行,则PL / SQL批量操作可能不会使事情明显地更有效。 如果瓶颈正在执行SQL语句,则需要希望传入的表上都存在适当的索引。如果瓶颈是insert_record过程,我们需要知道该过程在做什么以进行注释。

第三,如果insert_record过程(至少主要是)只是将您获取的数据插入到另一个表中,则摆脱所有循环并仅生成动态INSERT语句将更加有效。

第四,关于您的编辑,不能将绑定变量用于表名或列名,因此您提出的语法无效。 它不会更加高效,因为它将生成大量语法错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM