J'essaie de copier des enregistrements d'une table à l'autre le plus rapidement possible.Problème de performance avec Oracle BULK FETCH et FORALL insert
Actuellement, j'ai simple similaire boucle de curseur sur ceci:
FOR rec IN source_cursor LOOP
INSERT INTO destination (a, b) VALUES (rec.a, rec.b)
END LOOP;
Je veux accélérer ce pour être super rapide si je essaie quelques opérations VRAC (un VRAC Fetch, puis un insert FORALL):
Voici ce que j'ai pour l'insert bulk select/forall.
DECLARE
TYPE t__event_rows IS TABLE OF _event%ROWTYPE;
v__event_rows t__event_rows;
CURSOR c__events IS
SELECT * FROM _EVENT ORDER BY MESSAGE_ID;
BEGIN
OPEN c__events;
LOOP
FETCH c__events BULK COLLECT INTO v__event_rows LIMIT 10000; -- limit to 10k to avoid out of memory
EXIT WHEN c__events%NOTFOUND;
FORALL i IN 1..v__event_rows.COUNT SAVE EXCEPTIONS
INSERT INTO destinatoin
(col1, col2, a_sequence)
VALUES
( v__event_rows(i).col1, v__event_rows(i).col2, SOMESEQEUENCE.NEXTVAL);
END LOOP;
CLOSE c__events;
END;
Mon problème est que je ne vois pas de gros gains de performance jusqu'à présent. D'après ce que je lis, il devrait être 10x-100x plus rapide.
Est-ce qu'il me manque un goulot d'étranglement quelque part?
pour 100 000 lignes, cela prend environ 300 (!) Secondes même avec l'insertion en bloc – Will
Y a-t-il une raison pour laquelle vous avez un ORDER BY dans votre SELECT? Il pourrait être plutôt coûteux de trier 100 000 lignes et cela ne semble pas nécessaire. Votre vérification% NOTFOUND doit également se produire après votre FORALL-- sinon, si vous récupérez moins de 10 000 lignes dans la dernière itération, vous n'insérez pas ces lignes. –
merci! Je vais supprimer la commande par, mais je ne pense pas que cela va me faire tout à fait à la vitesse im la recherche ... je vais essayer d'obtenir une analyse tkprof et mettre à jour ce plus tard. bon attraper avec le% NOTFOUND – Will