0

我必须从运行时间定义的表中获取数据并根据运行时间定义的列获取数据,我现在使用带有 ref 游标的动态 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;
4

1 回答 1

0

首先,我不确定我是否理解代码在做什么。在您发布的代码中(您可能为了简化事情而减少了代码),该IF语句检查 which 是否是v_date_started IS NOT NULL多余的,因为. 它检查是否只是列上子句的冗余重复。它会检查哪个作为您构建的动态 SQL 语句中的附加子句是否更有效。在一个地方进行所有检查是有意义的,最有效的地方是在 SQL 语句中。WHEREDATE_STARTED(sysdate - v_date_started)*1440 > p_time_rangeWHEREDATE_STARTEDv_date_completed IS NULLWHERE

其次,这个查询应该返回多少行,花费的时间在哪里?如果游标可能返回许多行(对于许多行的某些定义),您将通过BULK COLLECT从游标到集合中执行 a 并修改insert_record过程以接受和处理集合来获得一些效率。如果时间都花在执行 SQL 语句上,而查询本身只返回少数几行,那么 PL/SQL 批量操作可能不会使事情变得更高效。如果瓶颈是执行 SQL 语句,您需要希望传入的任何表上都存在适当的索引。如果瓶颈是insert_record过程,我们需要知道该过程在做什么才能注释。

Third, if the insert_record procedure is (at least primarily) just inserting the data that you fetched into a different table, it would be more efficient to get rid of all the looping and just generate a dynamic INSERT statement.

Fourth, with respect to your edit, you cannot use bind variables for table names or column names so the syntax you're proposing is invalid. It won't be more efficient because it will generate a bunch of syntax errors.

于 2012-11-30T19:23:22.637 回答