Avatar billede Slettet bruger
25. november 2003 - 12:24 Der er 29 kommentarer

Performance for et script

Hej alle

Jeg har et problem. Jeg skal trække en del data ud fra en ascii fil og nedenstående script gør det rigtig men det tager laang tid. Er der nogen der kan se hvordan jeg kan optimere mit script så det går lidt hurtigere.

' Åbner en connection til ascii filen
Dim fso,f,filespec
Set fso = CreateObject("Scripting.FileSystemObject")
filespec = Server.Mappath("Min tekst fil")
Set f = fso.OpenTextFile(filespec,1)


Dim LinieP,arrP,RS3

'Funktion der fjerne evt ' omkring navne
function ReplaceP (arrP)
ReplaceP = Replace(Replace(arrP,"""",""),"'","")
end function

'Skal kun læse hvor 1. tal er 1
Do While not f.AtEndOfStream
LinieP = f.ReadLine
If Left(LinieP, 1) = "1" Then

'Laver et array der splitter linjer til senere udtræk fra db
arrP = Split(LinieP,",")

'Henter alt fra db hvor produkter er ens
Set RS3 = Conn.execute("Select * from Produktabel where ProduktNr = '"&arrP(1)&"'")
IF not RS3.EOF Then

'Opdaterer eksisterende menuer
Conn.execute("Update Produktabel Set MenuNr = '"&ReplaceP(arrP(2))&"',ProduktNavn = '"&ReplaceP(arrP(3))&"', ProduktNavnDK = '"&ReplaceP(arrP(4))&"', Pris = '"&ReplaceP(arrP(5))&"',Image = '"&ReplaceP(arrP(6))&"', Offer = '"&ReplaceP(arrP(7))&"', Godkendt = '"&ReplaceP(arrP(8))&"' where ProduktNr = '"&arrP(1)&"'")
else

'Indsætter nye menuer
Conn.execute("Insert into Produktabel(ProduktNr,MenuNr,ProduktNavn,ProduktNavnDK,Pris,Image,Offer,Godkendt) VALUES ('"&ReplaceP(arrP(1))&"','"&ReplaceP(arrP(2))&"','"&ReplaceP(arrP(3))&"','"&ReplaceP(arrP(4))&"','"&ReplaceP(arrP(5))&"','"&ReplaceP(arrP(6))&"','"&ReplaceP(arrP(7))&"','"&ReplaceP(arrP(8))&"')")
end if
RS3.close
Set RS3 = Nothing
End If
Loop
Avatar billede chriscross Nybegynder
25. november 2003 - 13:24 #1
Jeg ved ikke ligefrem om det hjælper fedt på din performance ( du er nødt til at gå i databasen for hver linie i din fil ) men der er ingen grund til at disse to linier:
Set RS3 = Conn.execute("Select * from Produktabel where ProduktNr = '"&arrP(1)&"'")
RS3.close
skal udføres for hver linie i din fil.

Hvis du erklærer og åbner dit recordset på følgende måde:
Set RS3 = Server.CreateObject("ADODB.Recordset")
RS3.Open str, Conn, adOpenStatic

- hvor str er din sql, så kan du erklære dit recordset i toppen, sætte det til Nothing i bunden, og så nøjes med at åbne og lukke det i din løkke.
Avatar billede chriscross Nybegynder
25. november 2003 - 13:34 #2
Og så ved jeg ikke om du ikke bruger ekstra ressourcer på at have din egen Replace-metode som du kalder i stedet for at kalde Replace() direkte
- men som jeg se det er det da et ekstra kald der udføres 8-9 gange for hver linie...
Avatar billede Slettet bruger
25. november 2003 - 13:34 #3
Hvis vi nu udelukker visse features i scriptet er der så en måde man kan køre scriptet uden at skulle åbne for linje?

Eksempelvis hvis man kunne sammenligne txt filen og databasen og opdatere i et huk?
Avatar billede chriscross Nybegynder
25. november 2003 - 13:41 #4
Jeg sad lige og tænkte på om der i din tabel vil være poster som ikke er i din fil ?
Fordi ellers kunne det vise sig at være hurtigere at slette tabellen og derefter indsætte dine linier - du ville slippe for løkken og inserts tager ikke så lang tid. Men du ved bedst selv om der på denne måde vil være risiko for fejl ( kan din fil indeholde fejl osv.), fordi hvis det går rigtig galt har du jo ikke så mange data tilbage i din tabel...
Men hilken database arbejder du med, og ligger dit filformat fast eller kan der være udsving hvis du er uheldig?
Avatar billede chriscross Nybegynder
25. november 2003 - 13:41 #5
slette indholdet af tabellen mener jeg ;-)
Avatar billede Slettet bruger
25. november 2003 - 13:53 #6
Hejsa...tak for hjælpen so far...er virkelig på skideren...Gider du lige uddybe det med replace funktionen?
Avatar billede chriscross Nybegynder
25. november 2003 - 14:00 #7
Jo du har lavet din egen replaceP(), indeni den kalder du VBScript's egen Replace().
I din sql: ('"&ReplaceP(arrP(1))&"','"& osv
I stedet for:
('"&Replace(Replace(arrP(1),"""",""),"'","")&"','"&

Ovenstående ser selvfølgelig ikke pænt ud - alternativt kan du hente variable ud fra dit array før du danner din sql:
var1 = Replace(Replace(arrP(1),"""",""),"'",""), og så bruge var1 i din sql - og det samme med de andre variable selvfølgelig, det vil gøre det mere overskueligt.
Avatar billede Slettet bruger
25. november 2003 - 14:03 #8
og hurtigere?
Avatar billede chriscross Nybegynder
25. november 2003 - 14:06 #9
Hov du har ikke svaret på det med databasen, fordi hvis det er MSSQL eller mySql kan man i hvertfald bruge en sql der ser sådan ud:

sql = "if exists(select ProduktNr from Produktabel where produktNr = '"&arrP(1)&"'") Begin Update Produktabel Set MenuNr = '"&ReplaceP(arrP(2))&"',ProduktNavn = '"&ReplaceP(arrP(3))&"', ProduktNavnDK = '"&ReplaceP(arrP(4))&"', Pris = '"&ReplaceP(arrP(5))&"',Image = '"&ReplaceP(arrP(6))&"', Offer = '"&ReplaceP(arrP(7))&"', Godkendt = '"&ReplaceP(arrP(8))&"' where ProduktNr = '"&arrP(1)&"' End Else Begin Insert Into Produkttabel (ProduktNr,MenuNr,ProduktNavn,ProduktNavnDK,Pris,Image,Offer,Godkendt) VALUES ('"&ReplaceP(arrP(1))&"','"&ReplaceP(arrP(2))&"','"&ReplaceP(arrP(3))&"','"&ReplaceP(arrP(4))&"','"&ReplaceP(arrP(5))&"','"&ReplaceP(arrP(6))&"','"&ReplaceP(arrP(7))&"','"&ReplaceP(arrP(8))&"')")

Altså en insert eller update i én - det burde overflødiggøre dit recordset hvis den sql kan eksekveres på din database
Avatar billede chriscross Nybegynder
25. november 2003 - 14:07 #10
>> og hurtigere

tja, det er vist minimalt - det vil det meste altså være når du har den løkke - det er den der trækker tænder
Avatar billede chriscross Nybegynder
25. november 2003 - 14:07 #11
Men kan du ikke sige mig hvilken database ?
Avatar billede chriscross Nybegynder
25. november 2003 - 14:10 #12
Fordi hvis din databse kan forstå exists-statements så burde du kunne mærke en forbedring af performance ved at bruge en sådan - du slipper nemlig for at åbne og lukke et recordset hver gang og det gør den langsom - det er ikke nødvendigvis selve løkken som jeg lige kom til at skrive - men det der sker i den...
Avatar billede Slettet bruger
25. november 2003 - 14:16 #13
det er en ms sql
Avatar billede Slettet bruger
25. november 2003 - 14:18 #14
kan jeg undgå løkken?
Avatar billede chriscross Nybegynder
25. november 2003 - 14:20 #15
Jamen så burde den kunne forstå det.
Altså prøv så at indsætte:
sql = "if exists(select ProduktNr from Produktabel where produktNr = '"&arrP(1)&"'") Begin Update Produktabel Set MenuNr = '"&ReplaceP(arrP(2))&"',ProduktNavn = '"&ReplaceP(arrP(3))&"', ProduktNavnDK = '"&ReplaceP(arrP(4))&"', Pris = '"&ReplaceP(arrP(5))&"',Image = '"&ReplaceP(arrP(6))&"', Offer = '"&ReplaceP(arrP(7))&"', Godkendt = '"&ReplaceP(arrP(8))&"' where ProduktNr = '"&arrP(1)&"' End Else Begin Insert Into Produkttabel (ProduktNr,MenuNr,ProduktNavn,ProduktNavnDK,Pris,Image,Offer,Godkendt) VALUES ('"&ReplaceP(arrP(1))&"','"&ReplaceP(arrP(2))&"','"&ReplaceP(arrP(3))&"','"&ReplaceP(arrP(4))&"','"&ReplaceP(arrP(5))&"','"&ReplaceP(arrP(6))&"','"&ReplaceP(arrP(7))&"','"&ReplaceP(arrP(8))&"') End"

Lige der hvor du åbner dit recordset, kommenter så alt med dit recordset + din IF-sætning ud og se hvad der sker. Skriv den evt ud og kør den direkte på databasen for at teste ) hurtigere og nemmere at fejlfinde syntaksfejl osv
Avatar billede chriscross Nybegynder
25. november 2003 - 14:21 #16
>> Kan jeg undgå løkken?

Ikke umiddelbart, men hvis du kan undgå at åbne og lukke et recordset i din løkke så vil det blive væsentlig hurtigere
Avatar billede chriscross Nybegynder
25. november 2003 - 14:23 #17
Jeg fandt lige en syntaks fejl, den er væk her:

sql = "if exists(select ProduktNr from Produktabel where produktNr = '"&arrP(1)&"') Begin Update Produktabel Set MenuNr = '"&ReplaceP(arrP(2))&"',ProduktNavn = '"&ReplaceP(arrP(3))&"', ProduktNavnDK = '"&ReplaceP(arrP(4))&"', Pris = '"&ReplaceP(arrP(5))&"',Image = '"&ReplaceP(arrP(6))&"', Offer = '"&ReplaceP(arrP(7))&"', Godkendt = '"&ReplaceP(arrP(8))&"' where ProduktNr = '"&arrP(1)&"' End Else Begin Insert Into Produkttabel (ProduktNr,MenuNr,ProduktNavn,ProduktNavnDK,Pris,Image,Offer,Godkendt) VALUES ('"&ReplaceP(arrP(1))&"','"&ReplaceP(arrP(2))&"','"&ReplaceP(arrP(3))&"','"&ReplaceP(arrP(4))&"','"&ReplaceP(arrP(5))&"','"&ReplaceP(arrP(6))&"','"&ReplaceP(arrP(7))&"','"&ReplaceP(arrP(8))&"') End"
Avatar billede chriscross Nybegynder
25. november 2003 - 14:24 #18
Og dermed bliver din fulde kode:
' Åbner en connection til ascii filen
Dim fso,f,filespec
Set fso = CreateObject("Scripting.FileSystemObject")
filespec = Server.Mappath("Min tekst fil")
Set f = fso.OpenTextFile(filespec,1)


Dim LinieP,arrP,RS3

'Funktion der fjerne evt ' omkring navne
function ReplaceP (arrP)
ReplaceP = Replace(Replace(arrP,"""",""),"'","")
end function

'Skal kun læse hvor 1. tal er 1
Do While not f.AtEndOfStream
LinieP = f.ReadLine
If Left(LinieP, 1) = "1" Then

conn.execute( "if exists(select ProduktNr from Produktabel where produktNr = '"&arrP(1)&"') Begin Update Produktabel Set MenuNr = '"&ReplaceP(arrP(2))&"',ProduktNavn = '"&ReplaceP(arrP(3))&"', ProduktNavnDK = '"&ReplaceP(arrP(4))&"', Pris = '"&ReplaceP(arrP(5))&"',Image = '"&ReplaceP(arrP(6))&"', Offer = '"&ReplaceP(arrP(7))&"', Godkendt = '"&ReplaceP(arrP(8))&"' where ProduktNr = '"&arrP(1)&"' End Else Begin Insert Into Produkttabel (ProduktNr,MenuNr,ProduktNavn,ProduktNavnDK,Pris,Image,Offer,Godkendt) VALUES ('"&ReplaceP(arrP(1))&"','"&ReplaceP(arrP(2))&"','"&ReplaceP(arrP(3))&"','"&ReplaceP(arrP(4))&"','"&ReplaceP(arrP(5))&"','"&ReplaceP(arrP(6))&"','"&ReplaceP(arrP(7))&"','"&ReplaceP(arrP(8))&"') End")
'Laver et array der splitter linjer til senere udtræk fra db
arrP = Split(LinieP,",")

'Henter alt fra db hvor produkter er ens
'Set RS3 = Conn.execute("Select * from Produktabel where ProduktNr = '"&arrP(1)&"'")
'IF not RS3.EOF Then

'Opdaterer eksisterende menuer
'Conn.execute("Update Produktabel Set MenuNr = '"&ReplaceP(arrP(2))&"',ProduktNavn = '"&ReplaceP(arrP(3))&"', ProduktNavnDK = '"&ReplaceP(arrP(4))&"', Pris = '"&ReplaceP(arrP(5))&"',Image = '"&ReplaceP(arrP(6))&"', Offer = '"&ReplaceP(arrP(7))&"', Godkendt = '"&ReplaceP(arrP(8))&"' where ProduktNr = '"&arrP(1)&"'")
'else

'Indsætter nye menuer
'Conn.execute("Insert into Produktabel(ProduktNr,MenuNr,ProduktNavn,ProduktNavnDK,Pris,Image,Offer,Godkendt) VALUES ('"&ReplaceP(arrP(1))&"','"&ReplaceP(arrP(2))&"','"&ReplaceP(arrP(3))&"','"&ReplaceP(arrP(4))&"','"&ReplaceP(arrP(5))&"','"&ReplaceP(arrP(6))&"','"&ReplaceP(arrP(7))&"','"&ReplaceP(arrP(8))&"')")
'end if
'RS3.close
'Set RS3 = Nothing
End If
Loop
Avatar billede chriscross Nybegynder
25. november 2003 - 14:28 #19
og så skal du lige fjerne min stavefejl i produktabel/produkttabel ;-)
Avatar billede Slettet bruger
25. november 2003 - 14:43 #20
du mener vel at arrayet skal over sql sætningen eller hvad
Avatar billede chriscross Nybegynder
25. november 2003 - 14:50 #21
Ja undskyld ;-)
Avatar billede Slettet bruger
25. november 2003 - 15:01 #22
Dit forslag virker fint men den er ikke meget hurtigere desværre..

Kan man ikke lave en sql sætning hvis vi nu siger den bare skal update a la

update bla bla where Left(LinieP, 1) = "1"???

Men hvordan skal den skrives?
Avatar billede chriscross Nybegynder
25. november 2003 - 15:08 #23
Nej det tror jeg ikke - du har jo flere linier der starter med 1..

Men har du prøvet at indsætte nogle
response.write "<br>hertil1" & Now
response.write "<br>hertil2"& Now
eks. lige efter din do while og lige efter din execute.
Bare for at se om det giver et hint om hvad der sløver den...
Det kan jo være det vil hjælpe at indlæse filen på en anden måde - måske i et hug og derefter splitte på linieskift så du har et array fyldt med linier hvor du kan hente hver enkelt linie ud og opdatere med....
Avatar billede chriscross Nybegynder
25. november 2003 - 15:17 #24
Jeg kan se at TextStream ( altså din variabel f ) har en metode der hedder readAll() hvis du nu læser den ind i en streng og derefter tester lidt på om du kan finde linieskift i din streng. Det kunne vel være chr(10) og chr(13) du skal forsøge at finde.
Hvis du kan skifte dem ud med et tegn der ellers ikke er i filen og derefter splitte på det tegn til et array du kan køre din løkke på.
Arrays er nemlig hurtige at arbejde med...jeg kender ikke hastigheden på readLine() men noget kører langsomt ved dig og der er ikke meget tilbage.

Hvordan tester du. Hjemmefra mod en eller anden server/et lejet domæne ?
Avatar billede Slettet bruger
25. november 2003 - 15:19 #25
jeg tror det der sløver den er 3900 produkter

det tager 16 sek på 512...spørgsmålet om er om det kan gøres hurtigere
Avatar billede Slettet bruger
25. november 2003 - 15:21 #26
lejet domæne mod udbyders server...jeg tænkte på at bruge read all men i dokumentationen skriver de at man skal bruge readline ved større filer da readall er meget ressource krævende...men et forsøg værd
Avatar billede chriscross Nybegynder
25. november 2003 - 15:26 #27
Prøvede du at udskrive de to steder ?
1600 produkter - det vil sige 3900 updates - det er da ikke dårligt på 16 sek. ;-)
- regn selv ud hvor mange pr. sek.

OK - er alle 3900 noget der er rettet ? Eller er der rettet i dem der starter med 1 ?
Og kunne du evt lave det så filen kun indeholdt dem der skal rettes/indsættes ?
Avatar billede chriscross Nybegynder
25. november 2003 - 15:42 #28
>>jean
Jeg har fået mail om at du har kommenteret ? men får ikke noget frem...
Jeg smutter lige om lidt men er tilbage fra imorgen tidlig om ikke andet ;-)
Avatar billede chriscross Nybegynder
25. november 2003 - 15:45 #29
Hov der er tidsforskydelse på indlæggende....

Nå det kan være de har ret ( i det med readAll ) - men har du så mulighed for at forkorte filen - lave noget forhånds-selektering ?
Hvordan foregår det - er det noget med at brugeren sidder og retter, trykker på en knap og så venter på skal blive færdigt ?
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
Kurser inden for grundlæggende programmering

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