PLSQL Performance发出多个模式的过程

时间:2019-01-03 10:39:35

标签: oracle plsql oracle11g

我有两个模式,LDS和LDSI。 (Oracle 11.2.0.3.0)

LDSI是类似于架构的接口,它充当一些基于队列/事件的架构。有一个充当队列列表的表以及一个处理它的调度作业。 (Create_Splits)

   PROCEDURE create_split_lots IS
        CURSOR splits IS
            SELECT   *
            FROM     ldsi_v_event_changes_base
            WHERE    interface_name = 'LDSI_SPLITS_MERGES'
            AND      (event_type = 'SPLIT_START')
            AND      transfer_state = 'N'
            AND      dml_operation = 'INS'
            ORDER BY event_ts ASC;  --FOR UPDATE NOWAIT

        l_log_id             NUMBER;
        l_lot_id             NUMBER;
        l_dependant_lot_id   NUMBER;
        l_event_date         DATE;
    BEGIN
        FOR lot IN splits LOOP
            BEGIN
                l_lot_id := lds_owner.lds_lot.get_or_create_lot(p_lotid => lot.lotid, p_system_code => lot.system_code);
                l_dependant_lot_id :=
                    lds_owner.lds_lot.get_or_create_lot(p_lotid => lot.dependant_lotid,
                                                        p_system_code => lot.dependant_system_code);

                IF l_lot_id IS NULL OR l_dependant_lot_id IS NULL THEN
                    raise_application_error(-20343,'error ' );
                END IF;

                lds_owner.lds_event.copy_events(p_source_lot_id => l_dependant_lot_id,
                                                p_target_lot_id => l_lot_id,
                                                p_until_date => l_event_date,
                                                p_deep_copy => TRUE);

                ldsi_lot_container_consumer.complete_get_event_change(p_id => lot.id);
                COMMIT;
            EXCEPTION
                WHEN OTHERS THEN
                    ROLLBACK;
                    ldsi_log.log_fatal_error(p_message => 'SQLCODE:' || SQLCODE || ' Message: ' || SQLERRM)                      
                    CONTINUE;
            END;
        END LOOP;
    END;

现在LDS_OWNER,是包含所有数据,批次信息,事件信息等的架构。 即使该呼叫没有没有任何事件本身已经在光标中测试了查询,该调用仍需要花费 ALWAYS 一分钟,

lds_owner.lds_event.copy_events(p_source_lot_id => l_dependant_lot_id,
                                                p_target_lot_id => l_lot_id,
                                                p_until_date => l_event_date,
                                                p_deep_copy => TRUE);

它驻留在LDS_OWNER模式上。代码逻辑很简单,有一个事件表,其中包含一个LOT的所有事件,该过程将所有事件从一个LOT复制到另一个。

 PROCEDURE copy_events (p_source_lot_id   IN lds_lots.id%TYPE,
                         p_target_lot_id   IN lds_lots.id%TYPE,
                         p_until_date      IN DATE DEFAULT SYSDATE,
                         p_deep_copy       IN BOOLEAN DEFAULT FALSE)
  IS
    l_log_id                     NUMBER;
    l_has_events                 BOOLEAN :=FALSE;

    CURSOR list_of_events (p_source_lot_id IN lds_lots.id%TYPE, p_target_lot_id IN lds_lots.id%TYPE)
    IS
      SELECT *
        FROM (
               SELECT p1.id,
                      p1.evtt_id,
                      p1.state,
                      p1.channel_type,
                      p1.hist_date,
                      p1.hist_seqnum,
                      p1.postponed_ny,
                      p1.postponed_by,
                      p1.postponed_date,
                      p1.target_area,
                      p1.escalated_ny,
                      p1.escalated_to,
                      p1.escalated_by,
                      p1.escalated_date,
                      p1.released_ny,
                      p1.released_by,
                      p1.released_date,
                      p1.created_by,
                      p1.created_date,
                      p1.modified_by,
                      p1.modified_date,
                      p1.lot_id,
                      p1.copy_ny,
                      CAST (p2.dependant_event_type AS VARCHAR2 (30))   AS copy_reason,
                      p1.parent_evt_id,
                      p1.origin_evt_id
                 FROM lds_events  p1
                      JOIN lds_v_event_changes_base p2
                        ON (p1.lot_id = p2.dependant_lotid
                        AND p2.dependant_lotid = p_source_lot_id
                        AND p2.lotid = p_target_lot_id) /*AND P2.EVENT_TYPE = 'SPLIT_START'*/
                WHERE p1.lot_id = p_source_lot_id
                  AND ((p1.origin_evt_id NOT IN (SELECT origin_evt_id
                                                   FROM lds_events
                                                  WHERE lds_events.lot_id = p_target_lot_id)
                     OR p1.origin_evt_id IS NULL)
                   AND NOT EXISTS
                         (SELECT 1
                            FROM lds_owner.lds_events
                           WHERE lds_owner.lds_events.lot_id = p_target_lot_id
                             AND p1.id = origin_evt_id))
                  AND p1.created_date < COALESCE (NULL, SYSDATE)
                  AND p1.state = 'OPEN'
                  AND p1.created_date < p2.event_ts
             );

    l_temp_event                 lds_events%ROWTYPE;
    l_event_reason_comment_rec   lds_comments%ROWTYPE;
    l_target_lot_varchar_id      VARCHAR2 (200);
    l_target_system_code         VARCHAR2 (200);
  BEGIN
    SELECT lotid,system_code
      INTO l_target_lot_varchar_id,l_target_system_code
      FROM lds_lots
     WHERE id = p_target_lot_id;


    FOR event IN list_of_events (p_source_lot_id, p_target_lot_id)
    LOOP
      l_has_events:=TRUE; 
      l_temp_event := NULL;
      l_temp_event := duplicate_event_row (event);

      l_temp_event.parent_evt_id := event.id;
      l_temp_event.lot_id := p_target_lot_id;
      l_temp_event.origin_evt_id := COALESCE (event.origin_evt_id, event.id);
      -- l_temp_event.copy_reason := event.dependant_event_type;

      l_temp_event.target_area :=
        COALESCE (ldsi_cspec.get_effective_event_area (p_channel_type    => event.channel_type,
                                                       p_lotid           => l_target_lot_varchar_id,
                                                       p_source_system   => l_target_system_code,
                                                       p_area            => event.target_area),
                  event.target_area);

      INSERT INTO lds_events VALUES l_temp_event
        RETURNING id INTO l_temp_event.id;

      l_event_reason_comment_rec := copy_comment (event.channel_type, l_temp_event.id, event.id);

      INSERT INTO lds_comments
           VALUES l_event_reason_comment_rec;

      -- COPY DOCUMENTS
      copy_documents (p_source_event => event.id, p_target_event => l_temp_event.id);
    END LOOP;

    IF l_has_events THEN    COMMIT; END IF;

  EXCEPTION
    WHEN OTHERS
    THEN
      ROLLBACK;
      RAISE;
  END copy_events;


FUNCTION duplicate_event_row (source_event IN lds_events%ROWTYPE)
    RETURN lds_events%ROWTYPE
  IS
    l_temp_event   lds_events%ROWTYPE;
  BEGIN
    l_temp_event := source_event;
    l_temp_event.id := NULL;
    l_temp_event.created_by := NULL;
    l_temp_event.created_date := NULL;
    l_temp_event.modified_by := NULL;
    l_temp_event.modified_date := NULL;
    l_temp_event.copy_ny := 'Y';
    RETURN l_temp_event;
  END duplicate_event_row;

编辑一个:毕竟,打开的光标可以缝合该问题。 查询说明计划:

Plan
SELECT STATEMENT  ALL_ROWSCost: 1,084  Bytes: 167  Cardinality: 1                       
    11 SORT ORDER BY  Cost: 1,084  Bytes: 167  Cardinality: 1                   
        10 FILTER               
            7 NESTED LOOPS ANTI  Cost: 1,083  Bytes: 167  Cardinality: 1            
                4 HASH JOIN  Cost: 1,080  Bytes: 160  Cardinality: 1        
                    2 TABLE ACCESS BY INDEX ROWID TABLE LDS_OWNER.LDS_EVENTS Cost: 2  Bytes: 96  Cardinality: 1     
                        1 INDEX RANGE SCAN INDEX LDS_OWNER.EVT_LOT_STATE_ESCALATED_I Cost: 1  Cardinality: 1  
                    3 TABLE ACCESS FULL TABLE LCC_OWNER.LCC_CIF_EVENT_CHANGES Cost: 1,077  Bytes: 2,880  Cardinality: 45    
                6 TABLE ACCESS BY INDEX ROWID TABLE LDS_OWNER.LDS_EVENTS Cost: 3  Bytes: 7  Cardinality: 1          
                    5 INDEX RANGE SCAN INDEX LDS_OWNER.EVT_LOT_FK_I Cost: 1  Cardinality: 3     
            9 TABLE ACCESS BY INDEX ROWID TABLE LDS_OWNER.LDS_EVENTS Cost: 3  Bytes: 7  Cardinality: 1              
                8 INDEX RANGE SCAN INDEX LDS_OWNER.EVT_LOT_FK_I Cost: 1  Cardinality: 3         

使用批量收集修改两个光标,性能更好。

1 个答案:

答案 0 :(得分:1)

我无法添加评论,所以我必须在这里回答-抱歉。

尝试对代码中的每个操作执行类似的操作

declare

  start_time        timestamp;
  end_time         timestamp;
  l_duration number(10,3); 
  begin
    start_time := systimestamp;
    do something..
    end_time := systimestamp;

    l_lock_duration := ROUND(EXTRACT( SECOND FROM end_time - start_time ) +
                       EXTRACT( MINUTE FROM end_time - start_time ) * 60 +
                       EXTRACT( HOUR   FROM end_time - start_time ) * 60 * 60,
                       3);
  end;

也许这样长的响应只是为了打开光标。第一步,您必须检查每个操作的持续时间。