Prestandaproblem i SQL-sats Du bör undvika UDFer och att köra sql-satser en gång för varje rad. Jag hade utgått från något liknande nedanstående SQL-sats, beroende på fullständigt schema och indexering. Tack för det svaret. Skall testa detta ikväll när jag kommer hem...Jag återkommer med resultatet... Tack för hjälpen än en gång. Läsningen av 3000 poster sjönk från 20 sekunder till 4 sekunder efter att ha lagt in den ena av dina lösningar. Lösningen för LogDate och LogComment tog längre(!) tid än den tidigare plus att den returnerade fel antal rader och det lyckades jag inte fixa till, så jag valde en annan lösning (jag bröt nog mot en normaliseringsregel eller möjligen två :-). Men det var det värt...måste släppa versionen idag :-) 4 sekunder är ju fortfarande ganska mycket. Känns som att det borde gå att se över indexeringen en del för att få bättre svarstid. Är det mycket även om det handlar om minst 10 joins, ett par sammansatta fält och 3000 poster? Visserligen är de flesta joinar enkla, det ligger ProjectID,StatusID o s v i tabellen och jag joinar för att få ProjectName, StatusName o s v. Återkommer med svar angående index-frågorna, har inte tid just nu. Testa att lägga det klustrade indexet på din foreign key istället. Det brukar hjälpa rätt bra. För den frågan jag skrev ovan bör du t ex ha ett icke-klustrat index på [Log] (TaskID, LogDate).Prestandaproblem i vy : SQL optimering
Jag har en ganska komplex vy som jag behöver hjälp med att optimera. Det är framförallt fem kolumner av två olika typer som ställer till det för mig. När jag kommenterar bort dessa fem fält så går det minst tio ggr snabbare.
1) För varje rad i vyn skall måste jag hämta två fält från den SENASTE posten i en loggtabell (som har ett fält TaskID som är kopplat till fältet ID i tabellen Task) :
Log-tabellen
-------------
TaskID
LogDate
LogComment
Taskview
-------------
CREATE VIEW TaskView
AS
SELECT bla,bla,bla,
(SELECT TOP 1 [Log].LogDate
FROM [Log] WHERE [Log].TaskID=Task.[ID]
ORDER BY LogDate DESC) AS LastChangeDate,
(SELECT TOP 1 [Log].LogComment
FROM [Log] WHERE [Log].TaskID=Task.[ID]
ORDER BY LogDate DESC) AS LastChange
FROM Task
Det här är ju inte alls bra och det slöar ner exekveringen ordentlig, det inser jag och det har jag verifierat att så är fallet. Jag vet att det finns bättre sätt att lösa det med joins (eller derived tables eller nåt sådant) men jag kan inte få det att fungera.
2) För varje rad i tabellen Task vill jag dessutom tre gånger hämta antalet poster i andra tabeller som är kopplade till den aktuella raden.
CREATE VIEW TaskView
AS
SELECT bla,bla,bla,
dbo.GetMessageCount(Task.MailBoxID) as MessageCount,
dbo.GetDocumentCount(Task.ID) as DocumentCount ,
dbo.GetConnectionCount(Task.ID) as ConnectionCount
FROM Task
Här har jag alltså gjort tre UDF:er som alla tre är triviala, typ
SELECT Count([ID]) FROM Rel_TaskDocument WHERE TaskID=@TaskID
Jag hade ju kunnat göra även dessa som subqueries men jag inbillade mig att det skulle vara snabbare om de var UDF:er. Har dock inte testat detta. Det slog mig nu när jag skriver detta att jag faktiskt inte behöver veta det exakta antalet, bara en 1:a om det existerar poster och en 0:a om det inte finns några. En omskrivning med EXISTS() skulle ju alltså antagligen hjälpa här. Kanske :
(CASE EXISTS(SELECT [TaskID] FROM Rel_TaskDocument WHERE TaskID=Task.[ID]) THEN 1 ELSE 0 END) AS DocumentCount
eller något liknande? Men är det snabbare?
Jag överväger att ta bort dessa och lägga till tre bit-fält i tabellen och uppdatera dessa i mina SP:s eller med triggers, när någon lägger till ett dokument eller meddelande...känns inte rätt, men prestandan är ett problem nu.
Totalt alltså ca 10 ggr så slött p g a dessa fem kolumner jag vill ha med mig tillbaka. Några tips?Sv: Prestandaproblem i vy : SQL optimering
<code>
SELECT t.*
, l.LogDate
, l.LogComment
, CASE WHEN rtd.TaskID IS NULL THEN 0 ELSE 1 END AS DocumentExists
FROM Task AS t
INNER JOIN (
SELECT TaskID, MAX(LogDate) AS LogDate
FROM [Log]
GROUP BY TaskID
) AS lmax ON t.[ID] = lmax.TaskID
INNER JOIN [Log] l ON lmax.TaskID = l.TaskID AND lmax.LogDate = l.LogDate
LEFT OUTER JOIN (
SELECT DISTINCT TaskID
FROM Rel_TaskDocument
) AS rtd ON t.[ID] = rtd.TaskID
</code>Sv:Prestandaproblem i vy : SQL optimering
Sv: Prestandaproblem i vy : SQL optimering
Sv:Prestandaproblem i vy : SQL optimering
Sv: Prestandaproblem i vy : SQL optimering
Du säger att jag borde se över indexeringen. Om jag har en typisk ProjectID/ProjectName-join mot Projecttabellen; då får jag väl ett klustrat index automatiskt på ID-kolumnen i Projekt-tabellen eftersom den är primarykey? Ska man utöver det har ett index på Task-tabellen som innehåller ProjectID? Och samma sak för alla andra "foreign keys"? Det blir ju väldigt många index på den tabellen då...
Jag skulle gärna lära mig mer om hur man optimerar t ex genom att analysera execution-plans. Speciellt nu när versionen är släppt och jag i lugn och ro kan ta tag i det. Problemet (förutom tidsaspekten) är att jag inte hittat någon riktigt bra källa...Har du någon bra artikel eller site som tar upp detta?Sv:Prestandaproblem i vy : SQL optimering
>Jag skulle gärna lära mig mer om hur man optimerar t ex genom att analysera execution-plans. Speciellt nu när versionen är släppt och jag i lugn och ro kan ta tag i det. Problemet (förutom tidsaspekten) är att jag inte hittat någon riktigt bra källa...Har du någon bra artikel eller site som tar upp detta?
Reklam för min kurs:
http://thinkdo.org/blogs/chris/archive/2005/01/04/158.aspx
Annars finns det tonvis med artiklar som tar upp sådant. Den bästa resursen (i mina ögon) är http://www.sql-server-performance.com/Sv: Prestandaproblem i vy : SQL optimering
/mickeSv:Prestandaproblem i vy : SQL optimering