PLSQL Performance выдает процедуру нескольких схем - PullRequest
0 голосов
/ 03 января 2019

У меня есть две схемы, 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, это схема, которая содержит все данные, информацию о партии, информацию о событиях и т. Д. Этот вызов занимает ВСЕГДА одну минуту, даже если у него нет событий Я сам проверил запрос в курсах, производительность там не проблема.

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 голосов
/ 03 января 2019

Я не могу добавлять комментарии, поэтому я должен ответить здесь - извините.

Попробуйте сделать что-то подобное для каждой операции в вашем коде

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;

Может, этот длинный ответ только для открытия курсора. Первый шаг, вы должны проверить продолжительность каждой операции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...