Oracle SQL insert grand ensemble de données de manière efficace par l'utilisation du curseur et commit unique
Le SQL suivant génère tous les enregistrements correspondants entre deux tables qui ont les mêmes schémas et procède ensuite à effectuer une itération sur le curseur qui stocke l'ensemble de résultats. - Je faire ligne par ligne insérer une validation à la fin de cette fonction. Ma question est comment puis-je obtenir le maximum de performance de ce type de requête? Code suit:
BEGIN
DECLARE
CURSOR foo IS
SELECT * FROM tableOne to
WHERE EXISTS (SELECT * FROM tableTwo tt
WHERE TO.FOO = TT.FOO
AND TO.BAR = TT.BAR); --THIS TAKES 5 MINUTES (66 MILLION ROWS)
BEGIN
FOR nextFoo IN foo
LOOP
INSERT INTO tracker t
(id,foo,bar,baz)
VALUES(trackerSequence.nextval, nextFoo.foo,nextFoo.bar,nextFoo.baz);
END LOOP;
COMMIT;
END;
END;
Cette requête peut prendre jusqu'à une heure et je suis en train de réduire le coût lié à elle. Je vais être le traitement de 140 millions d'enregistrements en général, donc je m'attends à le double de la quantité de temps cela prend. Toutes les colonnes sont indexées.
Informations de Version:
10g 10.2
- :Pourquoi vous n'avez pas essayé d'insertion en bloc?
- la première des cas de test, j'ai été fournis avec, pour les 10k enregistrements. J'ai couru dans un problème d'échelle tout à fait clairement. Merci de poster une réponse qui utilise bulk insert que cela serait bénéfique.
- :Quelle est votre version d'Oracle que vous utilisez?
- Oracle 10g 10.2
Vous devez vous connecter pour publier un commentaire.
comment sur
Je me demande si ce serait mieux optimisé.
Assurez-vous également que le dispositif de suivi -index de table sont désactivés lors de l'insertion d'..
ROLLBACK
segments et peut causer de graves journal d'archive de colmatage. En particulier, si le traitement de 140 mn lignes.OK, je sais que tu voulais le curseur...
Le seul avantage réel à l'aide du curseur, c'est commettre tous les 10k? les lignes lors du traitement d'une quantité de données pour éviter de remplir les journaux jusqu'.
À moins que vous vraiment besoin de l'aide du curseur, Éliminer la ligne de traitement.
Chemin Direct Insert de pointe, comme l'a suggéré
insert/*+append*/ into tracker....
BULK COLLECT
vous devriez vraiment avoir unLIMIT
. L'extraction de 66 millions de lignes de données dans la base de données de la PGA va créer des problèmes de performances. Si chaque ligne est à seulement 100 octets, par exemple, qui nécessiterait ~6 GO de la PGA de l'espace. La plupart des serveurs de bases de données ne vont pas être configuré pour permettre que beaucoup de la PGA de l'espace pour être consommé. Si vous arrive d'être sur une machine qui a des tonnes de RAM allouée à Oracle, un processus de mastication jusqu'à 6 GO de PGA va avoir un sérieux rendement négatif des répercussions sur d'autres processus dans la base de données.LIMIT
n'est pas vraiment dépendre sur le serveur. Le plus efficaceLIMIT
est généralement quelque part entre 100 et 1000. Vous pouvez essayer différents choix pour votre processus particulier s'il est peu probable que la différence va être énorme. Une "LIMITE" de 100 élimine 99% des contexte des changements, uneLIMIT
de 1000 élimine 99,9% des le cadre des quarts de travail. Il est peu probable que vous allez obtenir beaucoup plus de gain de performance de l'élimination de ce dernier 0,1% de la contexte de changements et d'augmenter la quantité de RAM que vous utilisez est susceptible d'ajouter plus de vos frais généraux que vous gagnez.Premier - comment pouvez-vous optimiser votre PL/SQL de la performance:
De deuxième ne pas faire l'insert avec PL/SQL. Utilisation BulkLoading (comme l'a déjà suggéré par certains commentaires). vous pouvez facilement trouver beaucoup d'infos sur BulkLoading si vous faites une recherche Google pour "oracle sql loader"
J'ai presque toujours reçu de meilleures performances avec ces données en vrac inserts en utilisant une combinaison de
BITMAP INDEXES
et à l'aide d'un chef de projet (Chemin Direct de la Charge) c'est à dire avec l'utilisation de l'indice de/*+ APPEND+/
.Je pourrait également supposer que ce serait bon d'index sur les deux
TT.FOO, TT.BAR
etTO.FOO, TO.BAR
.Donc somethink comme
Aussi Garder à l'esprit que la
EXIST
clause peut mordre retour dans certaines situations. Donc, vous souhaiterez peut-être utiliser simple, les jointures externes.Souviens - chef de projet (chemin Direct de la charge) ne sera pas toujours d'améliorer les performances de votre requête, il peut l'améliorer (ou aide) si votre table est correctement partitionné.
Essayer d'Expliquer le plan sur ces requêtes afin de trouver la meilleure.
Aussi, (comme l'un de la réponse mentionne déjà) ne pas s'engager à la fin, mais ne pas s'engager sur chaque dossier soit. Il est suggéré d'utiliser un point de validation quelque chose de similaire lors de l'utilisation
LIMIT XXXX
toutBULK COLLECT
ing. Votre commit points régissent la taille de votreROLLBAK
segments sont. Vous pouvez également utiliser votre coutume de Commettre des points (aussi simple que comptoir) de la procédure (c'est à dire dans un PLSQL BLOC).Les performances de la requête dépend aussi de la
HWM
de votre table (pour être précis), il faudrait presque toujours envie de jouer sous leHWM
de la table. Alors queTRUNCATE
sur leTRACKER
table aidera à atteindre cet objectif, les données précédentes, il va être perdu, donc ce ne pouvait guère être une solution ici. Suivre cette AskTom lien pour apprendre comment trouverHWM
.INSERT
procédure pour être placé sur une application en temps réel, de son mieux adaptés que d'une 'nuit' par lot.J'ai trouvé ce qui suit va faire de 130 millions d'encarts dans environ 49 minutes.