Hej! Beror lite på hur ofta frågan körs och om det är viktigt att den går supersnabbt. Kanske skulle det vara snabbare om du inte konverterar datumen till strängar i villkoren Hej Tomas! Martins tips är bra, Hej Martin! select SalesUnit, DateDiff(dd, 0, SalesDate) DayDontUse,Hjälp med optimering av sqlfråga
Har en tabell (vi kan kalla den tabell1) som innehåller c:a 32 miljoner rader & en annan tabell (tabell2) som innehåller c:a 48 miljoner rader.
Använder Sql server 2005.
Deffenition tabell1:
----------------------
SalesId * (BigInt)
SalesDate (Datetime) (ex: 2007-10-01 12:34:12:111)
SalesUnit (Int)
IsEnabled (Boolean)
Deffenition tabell2:
----------------------
SalesId * (BigInt)
SalesRow * (Int)
Type (Int)
Amount (Decimal)
Jag har skrivit en fråga summerar Amount per typ, dag & SalesUnit för de som har IsEnabled=True.
Resultatet blir alltså ungefär så här:
SalesUnit | Date | Type | Amount
12 2007-10-01 5 12.000
12 2007-10-01 7 2.300.000
12 2007-10-02 4 4.545
... osv ...
Min fråga ser ut så här (den hämtar data för 7 dagar):
select SalesUnit,
convert(datetime, convert(char(10),date,101)) Date,
Tabell2.Type Type,
Sum(Tabell2.Amount) Amount
from Tabell1
inner join Tabell2 ON Tabell1.SalesId=Tabell2.SalesId
where
IsEnabled=1
AND
Date between '2007-11-01' and '2007-11-08'
AND
salesunit = 11
group by salesunit, convert(datetime, convert(char(10),date ,101)), tabell2.type
order by salesunit, convert(datetime, convert(char(10),date ,101)), tabell2.type
99% av raderna har IsEnabled=1
Antal rader som summeras efter att jag lagt in WHERE villkor på datum, salesunit & isenabled är C:a 10.000 rader i tabell1 & c:a 14.000 i tabell2. Output blir c:a 40 rader.
Är detta ett optimalt sätt att skriva frågan på, eller hur kan man skriva den bättre?Sv: Hjälp med optimering av sqlfråga
Så vitt jag kan bedöma ser frågan vettig ut, men hur är det med indexen?
Av exemplet verkar det som om det är tabeller där det sker relativt många insättningar/borttagningar(?)/uppdateringar - vilket slöas ner av för många (och oviktiga) index, så ha det i åtanke.Sv: Hjälp med optimering av sqlfråga
WHERE ...
AND
SalesDate BETWEEN ...
GROUP BY Salesunit, DATEDIFF(dd,0,SalesDate), tabell2.type
ORDER BY Salesunit, SalesDate, tabell2.type
Kanske är jag helt ute och cyklar men jag tror att det fungerar så här:
Om man använder en formel i WHERE så måste databasen applicera formeln på alla poster för att avgöra vilka som skall ingå. (dvs 32 miljoner styck convert(datetime, convert(char(10),date,101)) + 64 miljoner strängjämförelser)
Om man använder ett indexerat fält så kan urvalet ske redan i indexet.
Antag att du har SalesDate indexerat. Då skulle databasen kunna göra så här:
- Vilken är första post som är större än eller lika med startdatum.
- Vilken är sista post som är mindre än eller lika med slutdatum.
Vi har nu med bara två sökningar fått ner antalet poster till 10000 utan att ha utfört några beräkningar eller konverteringar alls.
Om du dessutom använder SalesData i order by så behöver databasen inte sortera slutresultatet heller eftersom det redan är sorterat i indexet.
Nu är det möjligt att sql optimeringen fixar ovanstående automatiskt men det kan vara värt att prova.Sv:Hjälp med optimering av sqlfråga
Tack för svaret.
Frågan körs inte så ofta några gånger per dag & användare, men den går lite för långsamt nu enligt min mening.
Ja, tabellerna uppdateras ofta. Det sker inserts flera gånger per minut. Update n´n gång då och då & delete är sällsynt.
Har följande index.
Tabell1:
Ett klustrat standardindex på SalesId nyckelen.
Ett index på SalesUnit (ASC), IsEnabled (ASC), Date (ASC), SalesId (ASC)
Tabell2:
Ett klustrat standardindex på SalesId, SalesRow nyckelen.Sv:Hjälp med optimering av sqlfråga
men jag tror att det viktigaste du ska kolla
är att du har indexerat alla fält som är relevanta.
I detta fall:
Tabell1.SalesId
Tabell2.SalesId
IsEnabled=1
Date
salesunit
tabell2.type
Det gör enorm skillnad, i synnerhet när vi pratar om miljontals poster.Sv:Hjälp med optimering av sqlfråga
Tack för svaret.
Du kan ha rätt i att frågan skulle gå snabbare om man slapp strängjämförelserna.
Hur skulle du föreslå att frågan skrivs? Jag vill ju att svaret ska ska grupperas per dag, men datumen lagras ju som dag & tid (datetime). Du föreslår en datediff och det funkar ju bra att använda. Har man en sådan i group by så måste ju dock syntaxen vara lika i select villkoret och där vill jag ju ha ett läsligt datum tillbaka, alltså inte datediff värdet. En variant är ju såhär, men vet inte om det är bättre än mina strängkonverteringar: convert(datetime, DATEDIFF(dd,0,date)).
När jag tittar på Execution planen, kan jag få lite olika resultat, men de vanliga verkar vara att den största krämen går åt när den joinar tabell1 & tabell2 genom att göra en clustered index seek med sökvillkoret Tabell1.SalesId=Tabell2.SalesId. Så här ser det ut:
Object
-----------
tabell2.PK_tabell2
Output list
-------------
tabell2.type, tabell2.amount
Seek predicates
------------------
tabell2.salesid=tabell1.salesidSv: Hjälp med optimering av sqlfråga
convert(SalesDate, convert(char(10),date,101)) Date,
Tabell2.Type Type,
Sum(Tabell2.Amount) Amount
from Tabell1
inner join Tabell2 ON Tabell1.SalesId=Tabell2.SalesId
where
IsEnabled=1 AND salesunit = 11 AND
SalesDate between { d '2007-11-01' } and { ts '2007-11-08 23:59:59' }
group by DayDontUse, tabell2.type
order by SalesDate, tabell2.type
Men åandrasidan har du ju inte SalesDate som index (bara texten) så då gör det nog ingen större skillnad