У меня есть две схемы, 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
Редактировать два измененных курсора с массовым сбором, производительность не лучше.