Just nu i M3-nätverket
Gå till innehåll

Bättre kod?


Cluster

Rekommendera Poster

Har en kodsnutt som räknar ut antal sålda produkter som jag tror kan optimeras en del (med bättre SQl-satser) men jag får inte riktigt till det. :thumbsdown:

 

Så här ser koden ut nu:[log]

[MÄRK]<%[/MÄRK]
[color="#0000ff"]Set[/color] conn = [b]Server[/b].[color="#0000ff"]CreateObject[/color]([GRÅ]"ADODB.Connection"[/GRÅ])
connStr = [GRÅ]"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\inetpub\data\dbfile001.mdb"[/GRÅ]
conn.open connStr

antProd=0
[color="#0000ff"]Set[/color] orderRS=Conn.[color="#0000ff"]Execute[/color]([GRÅ]"SELECT id FROM ordrar WHERE Month(betald)="[/GRÅ]&manad&[GRÅ]" AND Year(betald)="[/GRÅ]&thisYear&[GRÅ]""[/GRÅ])
[color="#0000ff"]If[/color] [color="#0000ff"]Not[/color] orderRS.EOF [color="#0000ff"]Then[/color]
   [color="#0000ff"]Do[/color] Until orderRS.EOF
      [color="#0000ff"]Set[/color] prodRS=conn.[color="#0000ff"]Execute[/color]([GRÅ]"SELECT SUM(prodAnt) FROM orderrader WHERE prodId IN(SELECT id FROM produkter WHERE kat=6) AND orderId="[/GRÅ]&orderRS([GRÅ]"id"[/GRÅ])&[GRÅ]""[/GRÅ])
      [color="#0000ff"]If[/color] prodRS(0)>0 [color="#0000ff"]Then[/color]
         antProd=antProd+prodRS(0)
      [color="#0000ff"]End[/color] [color="#0000ff"]If[/color]
      [color="#0000ff"]Set[/color] prodRS=[color="#0000ff"]Nothing[/color]
      orderRS.MoveNext
   [color="#0000ff"]Loop[/color]
[color="#0000ff"]End[/color] [color="#0000ff"]If[/color]
[color="#0000ff"]Set[/color] orderRS=[color="#0000ff"]Nothing[/color]

conn.close
[color="#0000ff"]Set[/color] conn=[color="#0000ff"]Nothing[/color]

[b]Response[/b].Write antProd
[MÄRK]%>[/MÄRK]

[/log]Någon som känner för att kasta ett öga på detta och komma med förslag på förbättringar?

 

 

/Cluster

------------------------------------------------------------

Ditt vetande är värdelöst om inte andra vet att du vet

-----------> http://eforum.kicks-ass.net <------------

 

[inlägget ändrat 2005-07-23 12:25:29 av Cluster]

Länk till kommentar
Dela på andra webbplatser

Det enda jag kan tänka mig är att du lägger in fältet betald i orderrader, din databas växer ju lite då men det blir ju bara en query som du gör. Du får göra en avvägning beroende på hur mycket plats du har och hur stor trafikbelastning det är till databasen.

 

 

("SELECT SUM(prodAnt) FROM orderrader WHERE Month(betald)="&manad&" AND Year(betald)="&thisYear&"")

[inlägget ändrat 2005-07-25 10:48:16 av geezer]

Länk till kommentar
Dela på andra webbplatser

Tack för input men det där har jag nog löst själv:

[log]

[MÄRK]<%[/MÄRK]
[color="#0000ff"]Set[/color] conn = [b]Server[/b].[color="#0000ff"]CreateObject[/color]([GRÅ]"ADODB.Connection"[/GRÅ])
connStr = [GRÅ]"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\inetpub\data\dbfile001.mdb"[/GRÅ]
conn.open connStr

startTimer = [color="#0000ff"]Time[/color]r
antProd=0
[color="#0000ff"]Set[/color] orderRS=Conn.[color="#0000ff"]Execute[/color]([GRÅ]"SELECT id FROM ordrar WHERE Month(betald)="[/GRÅ]&manad&[GRÅ]" AND Year(betald)="[/GRÅ]&thisYear&[GRÅ]""[/GRÅ])
[color="#0000ff"]If[/color] [color="#0000ff"]Not[/color] orderRS.EOF [color="#0000ff"]Then[/color]
   [color="#0000ff"]Do[/color] Until orderRS.EOF
      [color="#0000ff"]Set[/color] prodRS=conn.[color="#0000ff"]Execute[/color]([GRÅ]"SELECT SUM(prodAnt) FROM orderrader WHERE prodId IN(SELECT id FROM produkter WHERE kat=6) AND orderId="[/GRÅ]&orderRS([GRÅ]"id"[/GRÅ])&[GRÅ]""[/GRÅ])
      [color="#0000ff"]If[/color] prodRS(0)>0 [color="#0000ff"]Then[/color]
         antProd=antProd+prodRS(0)
      [color="#0000ff"]End[/color] [color="#0000ff"]If[/color]
      [color="#0000ff"]Set[/color] prodRS=[color="#0000ff"]Nothing[/color]
      orderRS.MoveNext
   [color="#0000ff"]Loop[/color]
[color="#0000ff"]End[/color] [color="#0000ff"]If[/color]
[color="#0000ff"]Set[/color] orderRS=[color="#0000ff"]Nothing[/color]
endTimer = [color="#0000ff"]Time[/color]r
timeToGenerate=endTimer-startTimer
[b]Response[/b].Write([GRÅ]"Antal sålda produkter: "[/GRÅ]&antProd&[GRÅ]" st<br>Tid att generera: "[/GRÅ]&timeToGenerate&[GRÅ]" sek<br><br>"[/GRÅ])

startTimer = [color="#0000ff"]Time[/color]r
[color="#0000ff"]Set[/color] RS=conn.[color="#0000ff"]Execute[/color]([GRÅ]"SELECT SUM(prodAnt) FROM orderrader WHERE prodId IN(SELECT id FROM produkter WHERE kat=6) AND orderId IN(SELECT id FROM ordrar WHERE Month(betald)="[/GRÅ]&manad&[GRÅ]" AND Year(betald)="[/GRÅ]&thisYear&[GRÅ]")"[/GRÅ])
   [color="#0000ff"]If[/color] RS(0)>0 [color="#0000ff"]Then[/color]
      antProd=RS(0)
   [color="#0000ff"]Else[/color]
      antProd=0
   [color="#0000ff"]End[/color] [color="#0000ff"]If[/color]
[color="#0000ff"]Set[/color] RS=[color="#0000ff"]Nothing[/color]
endTimer = [color="#0000ff"]Time[/color]r
timeToGenerate=endTimer-startTimer
[b]Response[/b].Write([GRÅ]"Antal sålda produkter: "[/GRÅ]&antProd&[GRÅ]" st<br>Tid att generera: "[/GRÅ]&timeToGenerate&[GRÅ]" sek"[/GRÅ])

conn.close
[color="#0000ff"]Set[/color] conn=[color="#0000ff"]Nothing[/color]
[MÄRK]%>[/MÄRK]

[/log]Genom att kombinera SQL-satserna så minskades tiden att ta fram statistiken till ca 15-20% av ursprungstiden.

 

MEN, den kodsnutt som jag egentligen (inklistringsfel av mig) ville ha hjälp med är:

[log]

[MÄRK]<%[/MÄRK]
[color="#0000ff"]Set[/color] conn = [b]Server[/b].[color="#0000ff"]CreateObject[/color]([GRÅ]"ADODB.Connection"[/GRÅ])
connStr = [GRÅ]"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\inetpub\data\dbfile001.mdb"[/GRÅ]
conn.open connStr

antProd=0
[color="#0000ff"]Set[/color] orderRS=Conn.[color="#0000ff"]Execute[/color]([GRÅ]"SELECT id, antLev  FROM ordrar WHERE Month(betald)="[/GRÅ]&manad&[GRÅ]" AND Year(betald)="[/GRÅ]&thisYear&[GRÅ]""[/GRÅ])
[color="#0000ff"]If[/color] [color="#0000ff"]Not[/color] orderRS.EOF [color="#0000ff"]Then[/color]
[color="#0000ff"]Do[/color] Until orderRS.EOF			
	[color="#0000ff"]Set[/color] prodRS=conn.[color="#0000ff"]Execute[/color]([GRÅ]"SELECT SUM(prodAnt) FROM orderrader WHERE prodId IN(SELECT id FROM produkter WHERE kat<5) AND orderId="[/GRÅ]&orderRS(0)&[GRÅ]""[/GRÅ])										
	[color="#0000ff"]If[/color] prodRS(0)>0 [color="#0000ff"]Then[/color]
		antProd=antProd+(prodRS(0)*orderRS(1))
	[color="#0000ff"]End[/color] [color="#0000ff"]If[/color]
	[color="#0000ff"]Set[/color] prodRS=[color="#0000ff"]Nothing[/color]
	orderRS.MoveNext
[color="#0000ff"]Loop[/color]
[color="#0000ff"]End[/color] [color="#0000ff"]If[/color]
[color="#0000ff"]Set[/color] orderRS=[color="#0000ff"]Nothing[/color]

conn.close
[color="#0000ff"]Set[/color] conn=[color="#0000ff"]Nothing[/color]
[MÄRK]%>[/MÄRK]

[/log]

 

 

/Cluster

------------------------------------------------------------

Ditt vetande är värdelöst om inte andra vet att du vet

-----------> http://eforum.kicks-ass.net <------------

 

[inlägget ändrat 2005-07-25 11:52:04 av Cluster]

Länk till kommentar
Dela på andra webbplatser

HA! Nu fick jag även till den:[log]

[MÄRK]<%[/MÄRK]
[color="#0000ff"]Set[/color] conn = [b]Server[/b].[color="#0000ff"]CreateObject[/color]([GRÅ]"ADODB.Connection"[/GRÅ])
connStr = [GRÅ]"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\inetpub\data\dbfile001.mdb"[/GRÅ]
conn.open connStr

[color="#006400"]' Ursprunglig kod[/color]
startTimer = [color="#0000ff"]Time[/color]r
antProd=0
[color="#0000ff"]Set[/color] orderRS=Conn.[color="#0000ff"]Execute[/color]([GRÅ]"SELECT id, antLev  FROM ordrar WHERE Month(betald)="[/GRÅ]&manad&[GRÅ]" AND Year(betald)="[/GRÅ]&thisYear&[GRÅ]""[/GRÅ])
[color="#0000ff"]If[/color] [color="#0000ff"]Not[/color] orderRS.EOF [color="#0000ff"]Then[/color]
   [color="#0000ff"]Do[/color] Until orderRS.EOF         
      [color="#0000ff"]Set[/color] prodRS=conn.[color="#0000ff"]Execute[/color]([GRÅ]"SELECT SUM(prodAnt) FROM orderrader WHERE prodId IN(SELECT id FROM produkter WHERE kat<5) AND orderId="[/GRÅ]&orderRS(0)&[GRÅ]""[/GRÅ])                              
      [color="#0000ff"]If[/color] prodRS(0)>0 [color="#0000ff"]Then[/color]
         antProd=antProd+(prodRS(0)*orderRS(1))
      [color="#0000ff"]End[/color] [color="#0000ff"]If[/color]
      [color="#0000ff"]Set[/color] prodRS=[color="#0000ff"]Nothing[/color]
      orderRS.MoveNext
   [color="#0000ff"]Loop[/color]
[color="#0000ff"]End[/color] [color="#0000ff"]If[/color]
[color="#0000ff"]Set[/color] orderRS=[color="#0000ff"]Nothing[/color]
endTimer = [color="#0000ff"]Time[/color]r
timeToGenerate=endTimer-startTimer
[b]Response[/b].Write([GRÅ]"Antal sålda produkter: "[/GRÅ]&antProd&[GRÅ]" st<br>Tid att generera: "[/GRÅ]&timeToGenerate&[GRÅ]" sek<br><br>"[/GRÅ])


[color="#006400"]' Den nya klart optimerade koden:[/color]
strSQL=[GRÅ]""[/GRÅ]&_
[GRÅ]"SELECT SUM((sumAntLev*sumProdAnt)) FROM ( "[/GRÅ]&_
[GRÅ]"SELECT DISTINCTROW ordrar.antLev  AS [sumAntLev], Sum(orderrader.prodAnt) AS [sumProdAnt] "[/GRÅ]&_
[GRÅ]"FROM produkter INNER JOIN (ordrar INNER JOIN orderrader ON ordrar.ID = orderrader.orderId) "[/GRÅ]&_
[GRÅ]"ON produkter.id = orderrader.prodId "[/GRÅ]&_
[GRÅ]"GROUP BY ordrar.antLev, Month([betald]), Year([betald]), ordrar.ID, produkter.id, produkter.kat "[/GRÅ]&_
[GRÅ]"HAVING (((Month([betald]))=7) AND ((Year([betald]))=2005) AND ((produkter.kat)<5)))"[/GRÅ]

startTimer = [color="#0000ff"]Time[/color]r
antProd=0
[color="#0000ff"]Set[/color] RS=Conn.[color="#0000ff"]Execute[/color](strSQL)
[color="#0000ff"]If[/color] RS(0) [color="#0000ff"]Then[/color]
   antProd=RS(0)
[color="#0000ff"]End[/color] [color="#0000ff"]If[/color]
[color="#0000ff"]Set[/color] RS=[color="#0000ff"]Nothing[/color]
endTimer = [color="#0000ff"]Time[/color]r
timeToGenerate=endTimer-startTimer
[b]Response[/b].Write([GRÅ]"Antal sålda produkter: "[/GRÅ]&antProd&[GRÅ]" st<br>Tid att generera: "[/GRÅ]&timeToGenerate&[GRÅ]" sek"[/GRÅ])


conn.close
[color="#0000ff"]Set[/color] conn=[color="#0000ff"]Nothing[/color]
[MÄRK]%>[/MÄRK]

[/log]

[b]Resultatet[/b]
[i]Ursprunglig kod:[/i]
Tid att generera: 0.734375 sek

[i]Nya koden:[/i]
Tid att generera: 0.046875 sek

 

[FET]Tråden löst![/FET]

 

/Cluster

------------------------------------------------------------

Ditt vetande är värdelöst om inte andra vet att du vet

-----------> http://eforum.kicks-ass.net <------------

 

Länk till kommentar
Dela på andra webbplatser

Tyckte att den första sub-selecten dög, men den sista här är ju fet. Hade nog inte kommit på den av mig själv, hur kom du på det hela? Att använda join för att välja orderid och sedan välja alla orderrader med detta orderid är ju genialt.

 

Länk till kommentar
Dela på andra webbplatser

Tyckte att den första sub-selecten dög, men den sista här är ju fet.
Rätt nöjd själv faktiskt:)

 

hur kom du på det hela?

Läste på lite om inner join, testade mig fram och måste jag erkänna; tog hjälp av både "fråge-guiden" i Access och SQL Query Analyser.:thumbsup:

 

 

/Cluster

------------------------------------------------------------

Ditt vetande är värdelöst om inte andra vet att du vet

-----------> http://eforum.kicks-ass.net <------------

 

Länk till kommentar
Dela på andra webbplatser

Anjuna Moon
fick mig att förstå hur mycket ASP arbete man slipper om man kan göra riktiga querys. GO INNER JOIN!

Samtidigt måste man se till att skapa vettiga index på sina tabeller, annars kan joins resultera i väldigt långsamma queries.

 

Länk till kommentar
Dela på andra webbplatser

Anjuna Moon
Hur ska man placera sina indexeringar?

Det beror helt på behoven och var i systemet optimeringar krävs, det finns inga enkla regler.

 

Klustrade index använder du med fördel där optimering av datahämtning är viktigare än för lagring och hämtning. Övriga index skapar du efter behov ex. för att optimera sökningar på vissa specifika fält.

 

Jag har för mig att jag skrev ett detaljerat inlägg för länge sedan kring indexskapande, men hittar det inte just nu.

 

Vad jag förstår så tar indexeringarna en hel del plats.

I databasapplikationer är hastighet viktigare än minne (gäller väl f.ö allt i datavärlden, minne är ju i princip gratis, tid är mycket dyrbart)

 

Länk till kommentar
Dela på andra webbplatser

Arkiverat

Det här ämnet är nu arkiverat och är stängt för ytterligare svar.

×
×
  • Skapa nytt...