Avatar billede Nicolai Nybegynder
19. oktober 2012 - 09:53 Der er 9 kommentarer og
1 løsning

Hjælp til at gøre query lidt (meget) hurtigere...

Hej,

Jeg har en SQL database hvor jeg IKKE har mulighed for at påvirke hvordan data kommer ind, men jeg har en kolonne (Revenue) som desværre ligger som nvarchar og skal summeres. Eksempler på data der ligger i den kolonne er:

-2.451.251,98
85.004,52
520,41
-1,58

Alle ligger som NVARCHAR.

I dag summerer jeg kolonnen på følgende måde:

select SUM(case when charindex('-', Revenue) <> 0 then cast(replace(replace(replace(Revenue, '-', ''), '.', ''), ',','.') as decimal(25, 2)) * -1 when Revenue = '' then CAST('0' AS decimal(25,2)) when Revenue IS NULL then CAST('0' AS decimal(25,2)) when PATINDEX('%[^A-Z]%', Revenue) = 0 then CAST('0' AS decimal(25,2)) else cast(Replace(replace(Revenue, '.', ''), ',', '.') as decimal(25, 2)) end) AS Total FROM dbo.tblXSAP_Revenue WHERE ((Year = '" & RangeStartYear & "' AND Period IN (" & RangeStartMonths & ")) OR (Year = '" & RangeEndYear & "' AND Period IN (" & RangeEndMonths & "))) AND Right(BT,5) = '" & TeamCode & "'"

Det fungerer, men da tabellen består af +2.000.000 records tager det rigtig lang tid at lave denne summering (ca. 35 sekunder). Mine evner rækker ikke til det, men det bør være muligt at lave en mere "effektiv" query.

Serveren er SQL 2008 og jeg bruger Visual Basic 2010.
Avatar billede Slettet bruger
19. oktober 2012 - 10:31 #1
En lidt simpler convertering:
cast(replace(replace(Revenue,'.',''),',','.') as real)
Avatar billede softspot Forsker
19. oktober 2012 - 11:58 #2
Har du mulighed for at ændre på databaseschemaet? I så fald kunne du måske oprette et par ekstra kolonner, hvor data havde det rigtige format og så tilknytte en trigger, der formaterede data og gemte dem i de nye kolonner. Denne løsnings anvendlighed afhænger dog af, hvor ofte tabellen opdateres kontra hvor ofte denne forespørgsel skal foretages (bedst hvis der opdateres "sjældent" og læses ofte).
Avatar billede Nicolai Nybegynder
22. oktober 2012 - 16:04 #3
Jeg prøver at arbejde med at lave om i schemaet. Jeg får dog nye data ind hver dag, men da jeg selv konvertere dem bør jeg kunne ændre på dem.

Har testet "cast(replace(replace(Revenue,'.',''),',','.') as real)", men den giver ikke synlig hastighedsforbedring. Men det ser nemmere ud så jeg har lavet den ændring :)

Er "replace" funktionen "dyr" i ressourcer?
Avatar billede Syska Mester
22. oktober 2012 - 16:10 #4
SUM på 2 mill rækker er langsom ... end of discussion.

om 35 sek er for langtsom ... pas.

Men string vs int ... er der vist ingen tvivl om at int vil gøre en forskel.

Få lavet det skama om nu ... jeg græder hver gang jeg ser folk gemme tal/datoer som strings.

Derudover kan indexes også gøre en forskel. Men hvis du reelt vil lave en sum på det ... så er du nok bedre tjent med at køre et job om natten ... og så have det i den.
Avatar billede Nicolai Nybegynder
22. oktober 2012 - 16:13 #5
Jeg har ændret lidt i formatet, så nu ser min queary således ud:

select Year, Period, SUM(case when charindex('-', Revenue) <> 0 then cast(replace(replace(replace(Revenue, '-', ''), '.', ''), ',','.') as decimal(25, 2)) * -1 when Revenue = '' then CAST('0' AS decimal(25,2)) when Revenue IS NULL then CAST('0' AS decimal(25,2)) when PATINDEX('%[^A-Z]%', Revenue) = 0 then CAST('0' AS decimal(25,2)) else cast(Replace(replace(Revenue, '.', ''), ',', '.') as decimal(25, 2)) end) AS Total FROM dbo.tblXSAP_Revenue WHERE Right(BT,5) IN (" & TeamCode & ") GROUP BY Year, Period ORDER BY Year, Period

Nu fylder jeg en række datatables med informationen istedet og laver så en query på dem bagefter. Det ser ud som om at det gør søgningen hurtigere.

Men jeg er stadig meget interesseret i nogle ideer.
Avatar billede Nicolai Nybegynder
22. oktober 2012 - 16:17 #6
Hvis jeg laver en "Query Cost" avaluering, viser den at 99% af min cost ligger på Table Scan ad tblXSAP_Revenue.

Den kan jeg vil ikke undgå, så det betyder vel at jeg ikke kan gøre meget mere for at optimere den? Eller?
Avatar billede Nicolai Nybegynder
22. oktober 2012 - 16:19 #7
@Buzzzz: Du har nok ret...Shit in shit out! Jeg er nok nød til at bide i det sure æble og få lavet selve konverteringen om og i den forbindelse måske indexere...
Avatar billede Syska Mester
22. oktober 2012 - 16:25 #8
Hvis 2 mill er alle rows ... så er det rimelig naturligt den vil lave en table scan. I hvert fald ville det ikke være meget der kan optimeres med mindre du kan smide alle rows der bliver benyttet ind i et index og på den måde få et covering index.

Korrekt, alle databaser som er lavet med hovedet under armen yder ringe selvom man kaster det vildeste hardware gear efter den.
Avatar billede Nicolai Nybegynder
27. maj 2013 - 18:14 #9
@buzzzz, Det har taget lidt tid, men din "løsning" var den jeg valgte at gå videre med, og har nu en fantastisk performance. Smider du lige et svar... :)
Avatar billede Syska Mester
28. maj 2013 - 00:02 #10
Svar
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