2016-04-01 12 views
1

Ich habe eine sehr langsame SQL-Anweisung, die ich mit bedingten count() -Anweisungen optimieren kann, aber ich kann nicht herausfinden, wie dies zu tun ist.Effizientere SQL zum Zählen von mehreren Tabellen

SELECT TOP 10 U.UserID, 
       U.Fullname, 
       U.URL, 
       U.Fname, 
       U.ProfilePic, 

    (SELECT Count(ResourceID) 
    FROM resources R 
    WHERE R.UserID = U.UserID) AS ResourcesPosted, 

    (SELECT Count(JobID) 
    FROM Jobs J 
    WHERE J.UserID = U.UserID) AS JobsPosted, 

    (SELECT Count(AuditID) 
    FROM Audit_Trail AT 
    WHERE AT.UserID = U.UserID 
    AND TYPE = 1 
    AND Entry LIKE '%logged in%') AS TotalLogins, 

    (SELECT Count(EventID) 
    FROM Future_Events_Listing E 
    WHERE E.UserID = U.UserID) AS EventsPosted 
FROM User_basics U 
LEFT JOIN Pod_Membership PM ON PM.userID = U.UserID 
WHERE PodID = 268 

Könnte ich eine Art innerer Verbindung machen und dann die Elemente bedingt zählen?

+0

Ist 'PodID' in der' Pod_Membership' Tabelle? Wenn dies der Fall ist, sollte der "LINKE VERBINDUNGSBEGINN" ein "INNERER VERBINDUNGSBEREICH" sein, da der "WHERE" -Bestandteil dies ohnehin ist. – strickt01

+0

@ strickt01 danke, das habe ich jetzt gemacht. – chris

+0

Ist die Benutzer-ID in den Tabellen indiziert, in denen Sie den COUNT-Befehl ausführen, was ist Ihr wahrscheinliches Problem? Wenn zwischen den anderen Tabellen keine Verknüpfung besteht, auf die Sie sich als Benutzer-ID verlassen, dann gibt es keine Bedingung für den "COUNT", den Sie anwenden können, außer dem bereits in der WHERE-Klausel - d. H. UserID. – strickt01

Antwort

0

Verwenden Sie "erklären", um herauszufinden, wie die Abfrage ausgeführt wird.

Wenn es keine Indizes verwendet, indexieren Sie Ihre Tabellen. Als allgemeine Regel setzen Sie einen Index auf jedes Feld, das in einer WHERE-Klausel enthalten ist.

0

Es ist schwierig, genau zu sehen, wo der Engpass ohne einen Abfrageplan ist. Das wahrscheinlichste Problem ist, dass es keinen Index für UserID in den Tabellen gibt, in denen Sie die COUNT ausführen. Wenn dies der Fall ist, verursacht Ihre Abfrage einen vollständigen Tabellenscan für jede Tabelle für jeden Benutzer. Daher kann die folgende Abfrage helfen, diese Möglichkeit zu vermeiden, da sie nur einen Tabellenscan für jede Tabelle durchführt (obwohl die Indizierung von UserID die beste Lösung ist, da dies nur zu einer Indexsuche in jeder Tabelle führen sollte - mit der möglichen Ausnahme von Audit_trail müssen Type und Entry in Ihrem Index aufzunehmen, um eine potenziell sehr teuer Schlüsselsuche zu vermeiden):

SELECT TOP 10 U.UserID, 
      U.Fullname, 
      U.URL, 
      U.Fname, 
      U.ProfilePic, 
      ResourcesPosted, 
      JobsPosted, 
      TotalLogins, 
      EventsPosted 

FROM User_basics U 

INNER JOIN Pod_Membership PM ON PM.userID = U.UserID 
AND PodID = 268 

LEFT OUTER JOIN 
    (SELECT R.UserID, Count(ResourceID) AS ResourcesPosted 
    FROM resources R 
    GROUP BY R.UserID) res 
    ON res.UserID = U.UserID 

LEFT OUTER JOIN 
(SELECT J.UserID, Count(JobID) AS JobsPosted 
FROM Jobs J 
GROUP BY J.UserID) job 
ON job.UserID = U.UserID 

LEFT OUTER JOIN 
    (SELECT AT.UserID, Count(AuditID) AS TotalLogins 
    FROM Audit_Trail AT 
WHERE TYPE = 1 
AND Entry LIKE '%logged in%' 
GROUP BY AT.UserID) aud 
ON aud.UserID = U.UserID 

LEFT OUTER JOIN 
    (SELECT E.UserID, Count(EventID) AS EventsPosted 
    FROM Future_Events_Listing E 
    GROUP BY E.UserID) fut 
    ON fut.UserID = U.UserID 

So:

1) Wenn kein Index für UserId in einer oder allen Tabellen ist dann betrachten einen hinzufügen.

2) Wenn es ein Index für UserID auf Audit_Trail ist dann eine Schlüsselsuche zu vermeiden, müssen Sie möglicherweise Entry und Type als enthaltene Spalten hinzufügen. Sie müssen den Abfrageplan überprüfen, um dies zu beurteilen.