2017-04-20 9 views
0

ich eine ziemlich langsame Abfrage haben:MS Access - Geschwindigkeit Ausgabe

SELECT ticketnumber, stateactual, adj, 
    ConcatRelated("utilityname","IntTable","ticketnumber = """ & ticketnumber & """" & " AND " & "stateactual = """ & stateactual & """") AS utilities, 
    ConcatRelated("startupcustomer","IntTable","ticketnumber = """ & ticketnumber & """" & " AND " & "stateactual = """ & stateactual & """") as startdates 
INTO tixconcat 
FROM IntTable 
WHERE stateactual = "MT" 
GROUP BY ticketnumber, stateactual, adj; 

ich diese Herrenset concatrelated Abfrage verwendet:

http://allenbrowne.com/func-concat.html

Das funktioniert perfekt - aber es ist sehr langsam. Wie ein Rekord pro Sekunde. Ich versuche, dies auf 1,1 Millionen Aufzeichnungen zu machen, und ich brauche es wirklich irgendwann vor der nächsten Wahl. Irgendwelche Ideen?

Ich habe bereits die Datenbank komprimiert und repariert.

Danke!

+0

Denormalisierungsdaten haben ihre Nachteile. Sind Ihre Daten auf dem lokalen Computer oder greifen Sie über das Netzwerk auf den Server zu?Es könnte ein wenig schneller auf lokale Daten sein, aber ich bezweifle, dass es genug sein wird. – June7

+0

ConcatRelated sieht wie eine UDF (benutzerdefinierte Funktion) aus, die die Hauptursache für Geschwindigkeitsprobleme ist. UDFs sind sehr flexible Möglichkeiten, um Daten zu transformieren, aber sie in einer Abfrage mit Hunderttausenden oder Millionen von Zeilen zu verwenden, wird immer langsam sein. – Sorcefyre

+0

Haben die Felder [ticketnumber] und [stateactual] Indizes in der Tabelle [IntTable]? –

Antwort

0

Die Hauptsache, die Zeit nimmt, ist die ConcatRelated-Funktion. Es öffnet einen Tisch, durchsucht ihn, gibt ein Ergebnis und schließt dann den Tisch zweimal pro Reihe. Wenn Sie diesen Prozess beschleunigen möchten, müssen Sie SQL anstelle von benutzerdefinierten Funktionen verwenden, um Ihre Daten zu denormalisieren.

Um Ihre Felder zu verketten, ist dies der Prozess, den ich verwende, um es schnell zu machen.

Schritt 1 Verwenden Sie eine Kreuztabellenabfrage, um die Felder zu erhalten, die in einer Zeile verkettet werden sollen. Verwenden Sie Ihre Fremdschlüssel als Zeilenüberschriften, und das, was Sie da beide Spaltenüberschrift und Wert

Schritt 2 Concatenate die Spalten verketten möchten Sie aus der Kreuztabelle Abfrage

Schritt 3 Make verketten Ihre letzte Abfrage, und treten Sie der Abfrage/Ergebnis der Abfrage aus Schritt 2

Sie müssen 5 Abfragen verwenden (Schritt 1 und 2 einmal pro verkettetes Feld), aber es wird immer noch viel schneller als das, was Sie tun jetzt. Beachten Sie, dass Sie bereits in Schritt 1

Das Ergebnis filtern könnte etwas unterschiedlich sein, da ConcatRelated den gleichen Wert zweimal verketten kann, und mein Ansatz wird nicht

+0

Ich folge. Ich habe 1100 Fremdschlüssel. Keine Zeile im Endprodukt wird mehr als ein Dutzend haben. Glaubst du, dass es mit so vielen Spalten funktionieren wird? Ich muss vielleicht meinen Ansatz komplett überdenken. –

1

Eine Person in den Kommentaren der Indizierung der Felder hindeutet. Das hat geklappt - die gesamte Abfrage wurde in einer Stunde ausgeführt :)

0

Wie andere bemerkten, ist es nicht so sehr die Funktion für jede Zeile aufrufen (das ist teuer). Das Laden der SQL-Zeichenfolge, das Laden des Abfrageprozessors, das Überprüfen der SQL-Syntax und THEN JET/ACE müssen jedoch einen Abfrageplan erstellen, und DANN öffnen Sie die Tabelle, und DANN führen Sie die Abfrage aus, wo die Kosten liegen.

Was ich vorschlagen würde, die Abfrage-Prozessor umgehen und Öffnen der Tabelle direkt "einmal" am Anfang der Abfrage. Und das bedeutet, dass Sie den Befehl seek() verwenden, da er direkt auf den Index trifft und sql umgeht.

Public Function MyCon(vPK As Variant) As String 

    Static rst As DAO.Recordset 
    Static db As DAO.Database 
    Dim strV As String 
    Dim bolF As Boolean 
    'Stop 
    If rst Is Nothing Then 
    Set db = CurrentDb 
    Set rst = db.OpenRecordset("tblChild") 
    End If 

    With rst 
    .Index = "main_id" 
    .MoveFirst 
    .Seek "=", vPK 

    bolF = Not (.NoMatch) 
    Do While bolF 
     If MyCon <> "" Then MyCon = MyCon & "," 
     MyCon = MyCon & rst!InvoiceNumber 
     .MoveNext 
     If .EOF = True Then 
      bolF = False 
     Else 
      bolF = rst!main_id = vPK 
     End If 
    Loop 
    End With 


End Function 

HINWEIS in über die Verwendung von „statischen“ - das bedeutet, die Variable ihren Wert HÄLT - wir also nur öffnen Sie die Tabelle einmal: Dieser Code sollte etwa 1000 mal schneller laufen

.