2016-03-28 9 views
1

Ich schrieb einen Access-Client, um Vergleiche mit zwei Excel-Dateien zu machen. Es lädt die zwei Excel-Dateien, die verglichen werden, in temporäre Tabellen und wertet sie basierend auf den zwei unten gezeigten Abfragen aus.Warum dauert diese Zugriffsabfrage so lange?

Es gibt zwei Abfragen, da manchmal eine der Excel-Dateien nur eine Namensspalte hat. Im Grunde gibt der Benutzer den Namen der zu vergleichenden Spalten ein und wir ändern die Abfrage basierend darauf.

Die erste Abfrage, cQueryFull, funktioniert perfekt und sehr schnell (über 100k Datensätze in nur wenigen Sekunden). Die zweite Abfrage, cQueryPart, funktioniert (in Bezug auf den Vergleich) wie beabsichtigt, wurde jedoch nie auf Tabellen mit mehr als 5.000 Datensätze abgeschlossen. Es endet für Stunden und ich bin gezwungen, das Programm zu schließen.

Ich verstehe nicht, warum eine Abfrage so viel schneller ist als die andere und ich hatte gehofft, jemand könnte mir helfen, es herauszufinden und möglicherweise die zweite Abfrage zu beheben. Der Teil meines Zugriffsclients, der die Abfrage erstellt, lautet wie folgt:

If chkOneColumn.Value = 0 Then 
    ' Construct Comparison Query 
    qString = "SELECT OriginalFile." & txtOriginalFirst.Value & " as OriginalFirstName, OriginalFile." & txtOriginalMiddle.Value & " as OriginalMiddleName, OriginalFile." & txtOriginalLast.Value & " as OriginalLastName, WorkingFile." & txtWorkingFirst.Value & " as WorkingFirstName, WorkingFile." & txtWorkingMiddle.Value & " as WorkingMiddleName, WorkingFile." & txtWorkingLast.Value & " as WorkingLastName " _ 
      + "FROM OriginalFile, WorkingFile " _ 
      + "WHERE (OriginalFile." & txtOriginalFirst.Value & " not like WorkingFile." & txtWorkingFirst.Value & " or OriginalFile." & txtOriginalMiddle.Value & " not like WorkingFile." & txtWorkingMiddle.Value & " or OriginalFile." & txtOriginalLast.Value & " not like WorkingFile." & txtWorkingLast.Value & ") " _ 
      + "and OriginalFile." & txtOriginalAddress.Value & " = WorkingFile." & txtWorkingAddress.Value & " " _ 
      + "and OriginalFile." & txtOriginalDOB.Value & " = WorkingFile." & txtWorkingDOB.Value & " " 

    ' Open the record set 
    Set db = CurrentDb 
    Set qd = db.CreateQueryDef("cQueryFull") 
    With qd 
     .ReturnsRecords = True 
     .sql = qString 
    End With 
    DoCmd.OpenQuery "cQueryFull" 
ElseIf chkOneColumn.Value = -1 Then 
    ' Construct Comparison Query 
    qString = "SELECT OriginalFile." & txtOriginalFirst.Value & " as OriginalName, IIF(WorkingFile." & txtWorkingFirst.Value & " is null, '', WorkingFile." & txtWorkingFirst.Value & ") + IIF(WorkingFile." & txtWorkingMiddle.Value & " is null, '', ' '+WorkingFile." & txtWorkingMiddle.Value & ") + IIF(WorkingFile." & txtWorkingLast.Value & " is null, '', ' '+WorkingFile." & txtWorkingLast.Value & ") as WorkingName " _ 
      + "FROM OriginalFile, WorkingFile " _ 
      + "WHERE (OriginalFile." & txtOriginalFirst.Value & " not like '*'+WorkingFile." & txtWorkingFirst.Value & "+'*' or OriginalFile." & txtOriginalFirst.Value & " not like '*'+WorkingFile." & txtWorkingMiddle.Value & "+'*' or OriginalFile." & txtOriginalFirst.Value & " not like '*'+WorkingFile." & txtWorkingMiddle.Value & "+'*') " _ 
      + "and OriginalFile." & txtOriginalAddress.Value & " like WorkingFile." & txtWorkingAddress.Value + " " _ 
      + "and OriginalFile." & txtOriginalDOB.Value & " like WorkingFile." & txtWorkingDOB.Value & " " _ 

    ' Open the record set 
    Set db = CurrentDb 
    Set qd = db.CreateQueryDef("cQueryPart") 
    With qd 
     .ReturnsRecords = True 
     .sql = qString 
    End With 
    DoCmd.OpenQuery "cQueryPart" 
End If 

Kann jemand das Problem mit meiner Abfrage identifizieren? Falls es darauf ankommt, habe ich bereits versucht, die Tabellen zu indizieren, bevor die Abfrage erstellt und ausgeführt wird. Jede Hilfe würde sehr geschätzt werden!

Antwort

1

Es ist schwer zu sagen, aber ich vermute, dass das Problem mit den Kreuzverbindungen und der Anzahl der Prädikate (und Art der Prädikate) in der WHERE-Klausel (s) ist.

Das Verknüpfen von zwei Tabellen, wie Sie es tun, neigt dazu, eine sehr große Menge zu erstellen, die die WHERE-Klausel durchlaufen muss. Außerdem ist der LIKE-Operator in einer JET/ACE-Abfrage wahrscheinlich der langsamste Vergleichsoperator, der es gibt. Besonders LIKE mit einem führenden Wildcard (*).

Manchmal kommt man einfach nicht herum, aber manchmal ist es auch schneller, vorher abgefragte Teile in eine (noch andere) temporäre Tabelle zu laden und weitere Abfragen gegen diese Daten auszuführen.

Gibt es eine Möglichkeit, wie Sie Ihre WHERE-Klausel vereinfachen oder die Vergleichselemente in verschiedenen Stapeln so definieren können, dass Sie zuerst eine geradlinigere Abfrage ausführen und diese Ergebnisse dann weiter verarbeiten können? (Ich schlage vor, möglicherweise in temporäre Tabellen zu schreiben und weitere Abfragen durchzuführen, da Unterabfragen optimiert sind und nicht unbedingt garantieren, dass die "SQL-Logik", die Sie schreiben, so ist, wie sie tatsächlich ausgeführt wird).

+0

Gibt es irgendeine Art von Optimierung, an die Sie denken können, kann ich es versuchen? Es gibt nicht wirklich eine Möglichkeit für mich, ähnliche Vergleiche zu umgehen, da ich versuche, die Saite dreimal hintereinander in einer anderen Saite zu finden. Ich habe das Gefühl, dass es einen besseren Weg geben sollte, damit umzugehen, aber ich bin ratlos. Vielleicht habe ich zu lange damit angefangen. Könnten Sie auch erklären, was Sie mit den vorher abgefragten Teilen meinen? Denn wenn ich Sie richtig verstehe, kann ich die Tabellen nicht wirklich "vorfragen". – Vince

+0

Eigentlich habe ich einen Ratschlag bekommen und es geschafft, eine Lösung zu finden. Stattdessen analysiere ich die Daten in ein einzelnes Spaltenformat, um sie der ursprünglichen Datei zuzuordnen, und verwende dann eine andere Abfrage, um die analysierten Daten zu überprüfen. Dies eliminiert die Komplexität der where-Anweisung. Es funktioniert großartig. – Vince

+0

@Vince froh, dass Sie etwas gefunden haben ... Leider ist es viel zu schwierig, in diesen Angelegenheiten zu beraten, ohne das Umfeld zu verstehen, in dem Sie arbeiten. – jleach

Verwandte Themen