25. november 2008 - 10:06Der er
15 kommentarer og 1 løsning
Optimering af SELECT
Hejsa,
Jeg har følgende SELECT - som bliver brugt i en report i reporting services.
SELECT po.new_projektid, po.new_projektnummer, pr.new_name, ta.new_tegningsaftalenummer, po.new_posteringsdato, ta.new_antalanparter, ta.new_rykkerniveau, ta.new_betalingsaftalename, c.firstname + ISNULL(' ' + c.middlename, '') + ' ' + c.lastname AS kontaktnavn, c.address1_line1 + ISNULL(' ' + c.address1_line2, '') + ISNULL(' ' + c.address1_line3, '') + ' ' + ISNULL(c.address1_postalcode,'') + ' ' + ISNULL(c.address1_city,'') + ' ' + ISNULL(c.address1_country,'') AS adresse, c.new_kontaktpersonnr, ISNULL(po.New_Illikvidtbelb,0) AS belob, pot.saldo FROM (SELECT new_Tegningsaftalenummer, new_projektId, new_posteringsdato, new_Illikvidtbelb, new_Likvidtbelb, new_projektnummer, new_tegningsaftaleid FROM filterednew_post WHERE new_posteringsdato>='12-30-2008' AND new_posteringsdato<='12-31-2008' and new_posttype = 3 and statecode=0) AS po INNER JOIN FilteredNew_Projekt AS pr ON po.new_projektid = pr.new_projektid INNER JOIN FilteredNew_Tegningsaftale AS ta ON po.new_tegningsaftaleid = ta.new_tegningsaftaleid INNER JOIN FilteredContact AS c ON ta.new_kontaktid = c.contactid INNER JOIN (SELECT ISNULL(SUM(New_Illikvidtbelb), 0) + ISNULL(SUM(New_Likvidtbelb), 0) AS saldo, new_Tegningsaftalenummer, new_projektId FROM filterednew_post WHERE (new_posteringsdato <= DATEADD(hour, 23, '12-31-2008') and statecode=0) GROUP BY new_projektId, new_Tegningsaftalenummer) AS pot ON pot.New_projektId = ta.new_projektid AND pot.new_tegningsaftalenummer=ta.new_name ORDER BY po.new_projektnummer, ta.new_tegningsaftalenummer, po.new_posteringsdato
Der gemmer sig 287 rows under den første select - og kører man det hele sammen, så tager det over 1 time at eksekvere (gad ikke vente længere).
Tjekker jeg derimod mellem datoerne 29-11-08 og 30-11-08, hvor der er 6 rows, så kører den fint nok, på ca. 4,5 min.
Jeg har dog fundet ud af, at fjerner jeg ISNULL(SUM(New_Illikvidtbelb), 0) + ISNULL(SUM(New_Likvidtbelb), 0) AS saldo
Så kan den køre på 5 min, med de 287 rows. Mit spørgsmål er så, hvordan optimerer jeg denne, så den kommer til at køre hurtigt? Kan desværre ikke fjerne saldo fra den, som jeg har testet med - men lader til at det er den som er problemet..
Jeg er ikke sikker på, at det er bedre, men du kunne jo prøve at flytte lidt rundt på tabellerne og få to "ankre":
SELECT po.new_projektid, po.new_projektnummer, pr.new_name, ta.new_tegningsaftalenummer, po.new_posteringsdato, ta.new_antalanparter, ta.new_rykkerniveau, ta.new_betalingsaftalename, c.firstname + ISNULL(' ' + c.middlename, '') + ' ' + c.lastname AS kontaktnavn, c.address1_line1 + ISNULL(' ' + c.address1_line2, '') + ISNULL(' ' + c.address1_line3, '') + ' ' + ISNULL(c.address1_postalcode,'') + ' ' + ISNULL(c.address1_city,'') + ' ' + ISNULL(c.address1_country,'') AS adresse, c.new_kontaktpersonnr, ISNULL(po.New_Illikvidtbelb,0) AS belob, pot.saldo FROM ( SELECT ISNULL(SUM(New_Illikvidtbelb), 0) + ISNULL(SUM(New_Likvidtbelb), 0) AS saldo , new_Tegningsaftalenummer, new_projektId FROM filterednew_post WHERE new_posteringsdato <= DATEADD(hour, 23, '12-31-2008') and statecode=0 GROUP BY new_projektId, new_Tegningsaftalenummer) AS pot CROSS JOIN FROM filterednew_post po INNER JOIN FilteredNew_Projekt AS pr ON po.new_projektid = pr.new_projektid INNER JOIN FilteredNew_Tegningsaftale AS ta ON po.new_tegningsaftaleid = ta.new_tegningsaftaleid AND pot.New_projektId = ta.new_projektid AND pot.new_tegningsaftalenummer=ta.new_name INNER JOIN FilteredContact AS c ON ta.new_kontaktid = c.contactid WHERE po.new_posteringsdato>='12-30-2008' AND po.new_posteringsdato<='12-31-2008' and po.new_posttype = 3 and po.statecode=0 ORDER BY po.new_projektnummer, ta.new_tegningsaftalenummer, po.new_posteringsdato
(jeg tror jeg har fået det hen så resultatet bliver ens, men ingen garanti :-) )
og som altid er det en god idé at have indexerne i orden.
Da du mener, at det især er saldo-grupperingen der tager tid, vil det være et indlysende sted at starte: Opret et index med de to felter der grupperes på.
Jeg satte den til at køre den igennem i eftermiddags, og tjekkede så til den her for lidt siden - kan godt se jeg var lidt misvisende i hvad jeg sagde.. med ovenstående mente jeg den første query :) Men den tid passer også meget godt, hvis man regner den ud i forhold til hvor lang tid det tager et behandle de 6 rækker den ender ud med, når man tager datoerne i slutningen af november
Det er på de tabeller der er flest rækker i du vil få størst udbytte ud af at et eller flere index på de felter der bliver brugt til at joine på eller selektere på.
Jeg fandt løsningen ved at bruge INNER LOOP JOIN istedet for det sidste INNER LOOP
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.