2016-06-27 2 views
0

ich die unter Abfrage verwendet, die lange Zeit in Anspruch nahm auszuführen, da sie bekam 2 Millionen DatensätzeAlternative Art und Weise von Nicht in SQL existiert

DELETE 
AC 
FROM 
SGT_APPLICATION_CHECKLIST AC 
INNER JOIN SGT_APPLICATION_CHECKLIST_REF CR ON  AC.CHECKLIST_REF_ID =  CR.CHECKLIST_REF_ID 
INNER JOIN SGT_APPLICATION APP ON APP.APPLICATION_ID = AC.APPLICATION_ID 
WHERE 
NOT EXISTS 
(
SELECT 1 FROM SGT_APPLICATION_CHECKLIST SAC 
WHERE SAC.APPLICATION_ID = AC.APPLICATION_ID AND 
APP.APP_CATEGORY_VALUE = CR.APP_CATEGORY_VALUE 
AND APP.APP_SUB_CATEGORY_VALUE = CR.APP_SUB_CATEGORY_VALUE 
) 

So Was ist die alternative Möglichkeit der statt „existiert nicht“

+0

1 - langsam definieren. 2 bis 2 Millionen zu löschende Datensätze könnten aus vielen Gründen "langsam" sein, wie z. B. Trigger, Kaskaden, große Daten, aktualisierte Indizes usw. Haben Sie sich das angesehen? 3 - um 2 Millionen meinst du 2 Millionen zu filtern und löschen oder 2 Millionen insgesamt gelöscht werden? 4 - Bevor Sie versuchen, die Abfrage neu zu schreiben, haben Sie sich den Abfrageplan angesehen, um zu sehen, warum er langsam sein könnte? Sobald Sie das haben, sollten Sie es aufnehmen. – Igor

+0

Sie brauchen wahrscheinlich nur die entsprechenden Indizes für die Tabellen. –

+1

Konvertiere innere Anfrage in 'LINKE VERBINDUNG' s mit 'IS NULL'? Obwohl moderne Abfrageoptimierer wahrscheinlich so etwas selbst ausprobieren würden. –

Antwort

0

Sie können stattdessen eine LEFT JOIN versuchen.

--DELETE AC 
SELECT * -- So you can quickly copy&paste to try. :) 
FROM 
SGT_APPLICATION_CHECKLIST AC 
INNER JOIN SGT_APPLICATION_CHECKLIST_REF CR ON AC.CHECKLIST_REF_ID = CR.CHECKLIST_REF_ID 
INNER JOIN SGT_APPLICATION APP ON APP.APPLICATION_ID = AC.APPLICATION_ID AND APP.APP_CATEGORY_VALUE = CR.APP_CATEGORY_VALUE AND APP.APP_SUB_CATEGORY_VALUE = CR.APP_SUB_CATEGORY_VALUE 
LEFT JOIN SGT_APPLICATION_CHECKLIST SAC ON SAC.APPLICATION_ID = AC.APPLICATION_ID 
WHERE SAC.APPLICATION_ID IS NULL 

Obwohl theoretisch NICHT VORHANDEN scheint the best option zu sein.

Aber warum haben Sie diese Bedingungen zwischen APP und CR in der Unterabfrage? Ich habe sie auf die entsprechende INNER JOIN verschoben, aber Sie müssen überprüfen, ob das funktioniert.

0

Ich wette, ein linker äußerer Join wird in diesem Fall leistungsfähiger als Exists sein.

DELETE 
    AC 
    FROM 
    SGT_APPLICATION_CHECKLIST AC 
    INNER JOIN SGT_APPLICATION_CHECKLIST_REF CR ON  AC.CHECKLIST_REF_ID =  CR.CHECKLIST_REF_ID 
    INNER JOIN SGT_APPLICATION APP ON APP.APPLICATION_ID = AC.APPLICATION_ID 
    LEFT OUTER JOIN SGT_APPLICATION_CHECKLIST CR2 ON CR2.APPLICATION_ID = AC.APPLICATION_ID AND APP.APP_CATEGORY_VALUE = CR2.APP_CATEGORY_VALUE AND APP.APP_SUB_CATEGORY_VALUE = CR2.APP_SUB_CATEGORY_VALUE 
    WHERE 
    NOT CR2.APPLICATION_ID IS NULL 
0

Vor allem bewegen Bedingungen APP.APP_CATEGORY_VALUE = CR.APP_CATEGORY_VALUE und APP.APP_SUB_CATEGORY_VALUE = CR.APP_SUB_CATEGORY_VALUE aus Unterabfrage, weil sie nichts mit dieser Unterabfrage zu tun. Sie können bei vielen Parametern teilnehmen.

Join .... on A = B AND C = D 

Nun, über Ihre Frage, vorausgesetzt, Sie Ihre Unterabfrage gereinigt haben, dann tun es so, dass

select/delete .... 
FROM 
SGT_APPLICATION_CHECKLIST AC 
INNER JOIN SGT_APPLICATION_CHECKLIST_REF CR ON  AC.CHECKLIST_REF_ID =  CR.CHECKLIST_REF_ID 
INNER JOIN SGT_APPLICATION APP ON APP.APPLICATION_ID = AC.APPLICATION_ID 
.... other joins and changes i mentioned, etc... 
LEFT JOIN SGT_APPLICATION_CHECKLIST as SAC 
ON SAC.APPLICATION_ID = AC.APPLICATION_ID 
where SAC.APPLICATION_ID IS NOT NULL 

nur die Datensätze zu erhalten, die mit Ihrem SAC verbunden.