Just nu i M3-nätverket
Jump to content

Bättre kod?


Cluster

Recommended Posts

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]

Link to comment
Share on other sites

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]

Link to comment
Share on other sites

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]

Link to comment
Share on other sites

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 <------------

 

Link to comment
Share on other sites

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.

 

Link to comment
Share on other sites

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 <------------

 

Link to comment
Share on other sites

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.

 

Link to comment
Share on other sites

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)

 

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.



×
×
  • Create New...