Avatar billede the_raze Nybegynder
25. november 2008 - 10:06 Der 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..
Avatar billede a1a1 Novice
25. november 2008 - 11:31 #1
isnull er "tung", har du index på de 2 felter?

Ellers lav indexer på dem, så vil det nok blive hurtigere
Avatar billede the_raze Nybegynder
25. november 2008 - 13:12 #2
Skal den oprettes som ét index på New_Illikvidtbelob og New_Likvidtbelb eller skal der være to index, et for hver?

Synes umiddelbart ikke at der var nogen effekt da jeg prøvede.. Skal jeg gøre noget bestemt?
Avatar billede kjulius Novice
25. november 2008 - 22:49 #3
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.
Avatar billede the_raze Nybegynder
25. november 2008 - 23:02 #4
Får en fejl der hedder: Incorrect syntax near the keyword 'FROM'.

Som er ved:
CROSS JOIN FROM filterednew_post po
Avatar billede the_raze Nybegynder
25. november 2008 - 23:11 #5
ah ja.. from skulle selvf ikke være der :)
Har startet den for at se hvad der sker.. Kan meddele at ovenstående kører på 3 timer og 9 minutter..

Hvilke indexes vil i anbefale jeg opretter? og hvordan kan man se om mine indexes bliver brugt?
Avatar billede kjulius Novice
25. november 2008 - 23:17 #6
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å.
Avatar billede the_raze Nybegynder
25. november 2008 - 23:20 #7
kjulius: tusind tak for dit bud, men det gjorde den desværre langsommere :(
Avatar billede the_raze Nybegynder
25. november 2008 - 23:23 #8
..og det var selvfølgelig henvendt til din query :) Prøver lige det med index på saldo-grupperingen
Avatar billede kjulius Novice
25. november 2008 - 23:26 #9
De 3 timer og 9 minutter er vel et estimat? Eller kører tiden anderledes hos dig. Her er der højst gået et par min. ;-)
Avatar billede the_raze Nybegynder
25. november 2008 - 23:28 #10
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
Avatar billede the_raze Nybegynder
25. november 2008 - 23:28 #11
har lige kørt den igennem på november, efter jeg har tilføjet indexes.. Det ændrer intet :/
Avatar billede kjulius Novice
25. november 2008 - 23:34 #12
Hvilke af tabellerne indeholder flest rows (før udvælgelsen)?
Avatar billede kjulius Novice
25. november 2008 - 23:54 #13
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å.
Avatar billede the_raze Nybegynder
26. november 2008 - 08:24 #14
Der er 182000 rækker i filterednew_post..

Glemte at nævne det var et view - har indexes på tabellerne det bygger over, stadig en indflydelse? (synes nemlig ik det gør en forskel overhovedet)
Avatar billede kjulius Novice
26. november 2008 - 20:57 #15
Det vil jeg mene, men må indrømme at mine erfaringer med views på MS SQL Server ikke er store.
Avatar billede the_raze Nybegynder
22. marts 2009 - 19:38 #16
Jeg fandt løsningen ved at bruge INNER LOOP JOIN istedet for det sidste INNER LOOP
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester