2010-03-23 5 views
0

J'ai demandé hier un question qui a obtenu des réponses mais n'a pas répondu au point principal. Je voulais réduire le temps nécessaire pour faire une opération MINUS.ajouter au curseur dans l'oracle

Maintenant, je pense à faire MINUS opération dans les blocs de 5000, en ajoutant chaque résultat d'itérations au curseur et finalement retourner le curseur. Je suivais:

V_CNT   NUMBER :=0; 
V_INTERVAL  NUMBER := 5000; 

begin 
    select count(1) into v_cnt from TABLE_1 
while (v_cnt > 0) 
loop 
open cv_1 for 
    SELECT A.HEAD,A.EFFECTIVE_DATE, 
    FROM TABLE_1 A 
    WHERE A.TYPE_OF_ACTION='6' AND A.EFFECTIVE_DATE >= ADD_MONTHS(SYSDATE,-15) 
    AND A.ROWNUM <= V_INTERVAL 
    MINUS 
    SELECT B.head,B.EFFECTIVE_DATE, 
    FROM TABLE_2 B 
    AND B.ROWNUM <= V_INTERVAL 

V_CNT := V_CNT - V_INTERVAL; 
END LOOP; 
end; 

Cependant, comme vous le voyez ... à chaque itération le curseur est écrasé. Comment puis-je changer le code de sorte qu'à chaque itération il ajoute cv_1 au curseur plutôt que d'écraser?

+0

Il est très difficile de surpasser SQL avec pl/sql. Si l'opération est lente en ligne droite, elle restera probablement lente en pl/sql. –

+0

Je comprends cela. mais quand je le fais en lots de 5000. c'est assez rapide. – Omnipresent

+0

en lots de 5000 la requête prend 4 secondes par rapport à 8. donc je vais bien. en deuxième itération, cela prend encore 4 secondes ... et ainsi de suite. fondamentalement, chaque requête continue ne devrait pas prendre plus de 8 secondes. – Omnipresent

Répondre

0

Les curseurs ne fonctionnent pas ainsi, vous devez stocker les valeurs dans une sorte de collection.

Votre requête actuelle vous obtient 5000 lignes aléatoires de Table_1 et supprime les lignes qui existent également dans 5000 lignes aléatoires sélectionnées à partir de Table_2.


Avez-vous essayé de le faire sans MINUS?

Si je comprends bien la question, il devrait produire le même que celui-ci:

Select a.head, a.effective_date, 
From table_1 a 
Left Join table_2 b On (b.head = a.head And b.effective_date = a.effective_date) 
Where a.type_of_action='6' And a.effective_date >= ADD_MONTHS(SYSDATE,-15) 
    And b.head Is Null; 

avoir un indice composé sur TABLE_1 (type_of_action, head, effective_date) et TABLE_2 (head, effective_date) devrait vous aider à la performance.

+0

hmmm 5000 sont aléatoires mais finalement mon but est de couvrir toute la table non? ce qu'il fait? la jointure à gauche que vous avez fourni ne renvoie aucun résultat alors que le moins renvoie 60538 résultats .. – Omnipresent

+0

de votre exp ... l'approche de rownum sonne-t-elle ok ou puisque 5000 lignes sont sélectionnées aléatoirement .. elle ne sera pas cohérente sans rownum ? Je peux envisager de mettre des valeurs dans la collection et enfin les insérer dans le curseur – Omnipresent

+0

Je suppose que mon post devrait répondre, pourquoi vous obtenez des résultats différents dans les deux approches. –

1

Vous n'avez pas clairement énoncé l'exigence. Donc, je suppose, que vous voulez faire une Minus deux tables A et B. -à-dire que vous voulez trouver dans tuples A qui ne sont pas dans B.

En supposant cela, la logique que vous avez écrit est pas tout à fait correct, comme vous faites un MINUS sur les lots correspondants de A et B (5000 longueurs)

Par exemple: Votre logique retournera un tuple dans la 4000e rangée dans le tableau A, qui est présent, disons, le 6000e ligne de la table B.

Je vous suggère d'utiliser la jointure externe gauche pour répondre à vos besoins. (Même que le message de Peter Lang). Cela devrait suffire à vos exigences de performance, je pense.

Questions connexes