/ Forside / Teknologi / Udvikling / ASP / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
ASP
#NavnPoint
smorch 9259
Harlekin 1866
molokyle 1040
Steffanst.. 758
gandalf 657
smilly 564
gibson 560
cumano 530
MouseKeep.. 480
10  Random 410
Optimering af kode
Fra : Jon Klose Larsen


Dato : 09-05-05 16:30

Hej

Jeg har et script som i dag er skrevet efter følgende pseudo-kode....
*********************************
åben rs

loop gennem rs og hvis post findes
opdater post
ellers
opret post
end

rs.movefirst

loop gennem rs
hvis check1 <> X1
opdater post
end
hvis check2 = X2
opdater post
end

rs.movefirst

loop gennem rs
hvis check3 = X3
opdater post
end

rs.movefirst
osv.
*********************************
Dette gøres 5-6 gange.

Med nuværende script, så tager det ca. 7-11 sek. at løbe gennem de ca. 60-80
poster * 5-6 gange.
Nogle vil sige at det er lang tid, men det er ikke kun adgang til intern DB,
men også data-hentning fra ekstern kilde via nettet.

Jeg har kørt med forskellige timere i scriptet for at finde "tidsrøvere",
men er efterhånden så langt nede som jeg tror jeg kan. Nu vil jeg bare gerne
gøre det mindst muligt belastende for serveren/databasen.

Derfor vil jeg spørge om ovenstående måde, med at bruge det samme recordset,
er optimalt, i forhold til at åbne et nyt RS med specific angivelse af
posten (..... where post = xxxx), og derefter lukke efter den enkelte
opdatering ?

Jeg bruger Access DB og Win 2003 Server.

Jon



 
 
Jens Gyldenkærne Cla~ (09-05-2005)
Kommentar
Fra : Jens Gyldenkærne Cla~


Dato : 09-05-05 17:28

Jon Klose Larsen skrev:

> loop gennem rs og hvis post findes
> opdater post
> ellers
> opret post
> end

Helt gal fremgangsmåde. Du skal *aldrig* gennemløbe et postsæt for
at tjekke om en given post findes - brug *altid* en select-sætning
til det. Det er ikke bare hurtigere, men mange, mange gange
hurtigere.

Når du ikke ved om posten findes kan du gå frem på flere
forskellige måder. Den simple vil være følgende:

a)    Tjek om posten eksisterer =>
select count(*) as antal from tabel where [kriterium]

b) Hvis posten eksisterer (rs("antal") > 0), opdater =>
UPDATE tabel SET felt = nyværdi, ... WHERE [kriterium]

c) Hvis posten ikke findes (rs("antal") = 0), opret =>
INSERT INTO tabel (felt1, felt2, ...) VALUES (værdi1, værdi2, ...)

Det giver to sql-kald, intet gennemløb af poster og kun overførsel
af en enkelt værdi (antallet af poster der opfylder kriteriet) fra
databasen til asp-siden.

Ved at bruge fejlhåndtering kan man spare det ene kald væk i nogle
situationer. Tricket er at man antager at det er én af de to mulige
handlinger (opdatering eller oprettelse) der skal udføres - og når
man så har udført den, tjekker man om det gik godt.

Hvis man fx antager at posten findes i forvejen, kører man en
update-sætning og tjekker så hvor mange poster der blev ændret (via
egenskaben recordsaffected). Hvis der ikke er ændret nogen poster,
vil recordsAffected være 0, og så kan man så køre en insert-
forespørgsel.

Brugen af fejlhåndtering kan give en mindre forbedring i forhold
til den simple løsning, men selv den simple løsning vil være en
kæmpe forbedring i forhold til din nuværende løsning.

> loop gennem rs
> hvis check1 <> X1
> opdater post
> end
> hvis check2 = X2
> opdater post
> end
>
> rs.movefirst

Jeg forstår ikke helt hvorfor du opdaterer i små bidder i stedet
for at opdatere det hele på en gang. En update-sætning kan snildt
klare at opdatere samtlige felter på en gang (bortset fra
situationer med lange tekster i notatfelter).

Update-sætningen kan også fint opdatere flere poster på én gang,
hvis det er fælles værdier der skal tildeles.

Et par eksempler:

Opdater varetabellen, sæt alle priser op med 25 %:
   UPDATE varer SET pris = pris * 1.25

Opdater varetabellen, sæt alle priser op med 10 kr.
   UPDATE varer SET pris = pris + 10

Opdater varetabellen, sæt alle priser til 100 kr
   UPDATE varer SET pris = 100

Opdater varetabellen, sæt mindsteprisen på alle varer til 20 kr
   UPDATE varer SET pris = 20 WHERE pris < 20
--
Jens Gyldenkærne Clausen
Svar venligst under det du citerer, og citer kun det der er
nødvendigt for at forstå dit svar i sammenhængen. Se hvorfor og
hvordan på http://usenet.dk/netikette/citatteknik.html

Jon Klose Larsen (09-05-2005)
Kommentar
Fra : Jon Klose Larsen


Dato : 09-05-05 21:47


>
> Når du ikke ved om posten findes kan du gå frem på flere
> forskellige måder. Den simple vil være følgende:
>
> a) Tjek om posten eksisterer =>
> select count(*) as antal from tabel where [kriterium]
>
> b) Hvis posten eksisterer (rs("antal") > 0), opdater =>
> UPDATE tabel SET felt = nyværdi, ... WHERE [kriterium]
>
> c) Hvis posten ikke findes (rs("antal") = 0), opret =>
> INSERT INTO tabel (felt1, felt2, ...) VALUES (værdi1, værdi2, ...)
>
> Det giver to sql-kald, intet gennemløb af poster og kun overførsel
> af en enkelt værdi (antallet af poster der opfylder kriteriet) fra
> databasen til asp-siden.
>


Dette er hvad jeg kalder "gode informationer" ! Tak.

Et spørgsmål: Findes der andre måder end (a) ovenfor, som kan vise om en
post eksisterer ?
Grunden til jeg spørger er, at jeg tidligere er løbet i problemer, hvis jeg
har lavet udtræk som de fleste gange giver flere poster, men enkelte gange
giver ingen poster.... og det gav problemer. Jeg kan godt se at count kan
gøre det... jeg er bare interesseret i evt. yderligere muligheder.


> Ved at bruge fejlhåndtering kan man spare det ene kald væk i nogle
> situationer. Tricket er at man antager at det er én af de to mulige
> handlinger (opdatering eller oprettelse) der skal udføres - og når
> man så har udført den, tjekker man om det gik godt.
>
> Hvis man fx antager at posten findes i forvejen, kører man en
> update-sætning og tjekker så hvor mange poster der blev ændret (via
> egenskaben recordsaffected). Hvis der ikke er ændret nogen poster,
> vil recordsAffected være 0, og så kan man så køre en insert-
> forespørgsel.

Vil dette ikke give en fejl ?
Jeg mener bestemt at jeg får en fejl, hvis jeg prøver at update en post som
ikke findes.... men jeg kan da tage fejl - det vil jeg teste i morgen.

recordsaffected.... ??
Den har jeg aldrig hørt om.
Den vil jeg søge lidt på.... og prøve at finde andre egenskaber som åbenbart
kan være nyttige at kende.
>
> Brugen af fejlhåndtering kan give en mindre forbedring i forhold
> til den simple løsning, men selv den simple løsning vil være en
> kæmpe forbedring i forhold til din nuværende løsning.


Fejlhåndtering... det har ikke været min stærke side indtil nu - Når noget
gik galt, så har jeg kunnet programmere mig ud af det. Dette er dog ikke en
holdbar løsning.... det er jeg godt klar over. Har du nogle gode links til
sider der forklarer mere detaljeret om hvordan man kan bruge det (gerne med
eksempler) ?


>
> Jeg forstår ikke helt hvorfor du opdaterer i små bidder i stedet
> for at opdatere det hele på en gang. En update-sætning kan snildt
> klare at opdatere samtlige felter på en gang (bortset fra
> situationer med lange tekster i notatfelter).
>


Nu er mit eksempel ikke helt fyldestgørende... det var bare "kradset ned" i
en fart til brug her.
Grunden til at jeg gennemløber flere gange er, at kriterierne for de
forskellige updates er så forskellige og dog sammenhængende.
For at illustrere det i simpel form...

1) hent eksterne data og formater den, så de kan viderebehandles - lægges i
array

2) hent info om hvem der skal søges på (hvem er kendt i medlems-db) - lægges
i array (kun primær id)

3)loop gennem de to arrays og hvis ekstern = db så skal log-db opdateres
(status: online) - hvis brugeren ikke er kendt i log-db skal der oprettes
post

4) løbende check om anden ekstern parameter ændrer sig. Hvis denne går over
50 skal der opdateres yderligere felter, og hvis den derefter går under 50
igen, skal andre felter opdateres.

...... og sådan kan jeg blive ved.

??) til sidst skal jeg løbe hele log-db igennem for checke om nogle er
markeret som online, og de faktisk er logget af (ikke tilstede i eksterne
data længere). Så skal der opdateres for sidste gang.... i denne omgang.

Hele denne process gentages hvert andet minut.



> Update-sætningen kan også fint opdatere flere poster på én gang,
> hvis det er fælles værdier der skal tildeles.
>
> Et par eksempler:


Det var jeg godt klar over, men kan ikke bruges i mit tilfælde.
Ellers mange tak for info og specielt eksemplerne.

Jon



Jens B (14-05-2005)
Kommentar
Fra : Jens B


Dato : 14-05-05 14:46


"Jon Klose Larsen" <klose@post8fejl.tele.dk> skrev i en meddelelse
news:427fcc3e$0$159$edfadb0f@dtext02.news.tele.dk...
> Grunden til jeg spørger er, at jeg tidligere er løbet i problemer, hvis
> jeg har lavet udtræk som de fleste gange giver flere poster, men enkelte
> gange giver ingen poster.... og det gav problemer. Jeg kan godt se at
> count kan gøre det... jeg er bare interesseret i evt. yderligere
> muligheder.

Hvis jeg forstår dig rigtigt, så kunne det tyde på at du tit laver din Loop
sætning som:

Do
en hel masse....
rs.MoveNext
Loop While Not rs.EOF


Hvis du istedet skriver:

Do While Not rs.EOF
en hel masse...
rs.MoveNext
Loop

Så undgår du fejl i de tilfælde hvor der ikke findes poster der opfylder
dine kriterier.

Jens



Jens Gyldenkærne Cla~ (09-05-2005)
Kommentar
Fra : Jens Gyldenkærne Cla~


Dato : 09-05-05 22:39

Jon Klose Larsen skrev:

> Et spørgsmål: Findes der andre måder end (a) ovenfor, som kan
> vise om en post eksisterer ?

Ja. Du kan prøve at hente posten:

SELECT TOP 1 felt FROM tabel WHERE [kriterium]

- og så tjekke om det returnerede postsæt er tomt eller ej. Top 1
er taget med, fordi der ikke er grund til at hente flere poster
hvis man kun er interesseret i "eksisterer/ikke eksisterer"-
spørgsmålet.


> Grunden til jeg spørger er, at jeg tidligere er løbet i
> problemer, hvis jeg har lavet udtræk som de fleste gange giver
> flere poster, men enkelte gange giver ingen poster....

En SELECT COUNT giver altid poster (og uden group by altid én post)
- ellers er der noget galt med din sql-sætning.


> Jeg mener bestemt at jeg får en fejl, hvis jeg prøver at
> update en post som ikke findes....

Hvis du prøver at skrive til en post der ikke findes, får du en
fejl. Men hvis du bruger en update-sætning giver det ingen fejl
hvis der ikke er nogen poster der påvirkes.

Jeg kan fx fint skrive:

   UPDATE ansatte SET loen = 5 * loen WHERE 1 = 2

- uden at det påvirker årsregnskabet ;)

Det er helt tilsigtet at update virker således - der er masser af
tilfælde hvor man ikke er sikker på at der er nogen poster der
opdateres.


> recordsaffected.... ??
> Den har jeg aldrig hørt om.
> Den vil jeg søge lidt på....

<http://www.google.dk/search?q=ado+recordsaffected&btnI=Jeg+føler+mig+heldig>



> Fejlhåndtering... det har ikke været min stærke side indtil nu

- Så vent med at kigge på det til du har fået den simple løsning på
plads. Det er godt at kunne, men det er ikke så væsentligt i
forhold til dine aktuelle problemer.


> 1) hent eksterne data og

Hvorfra (database, application-variabel, ?)

> 2) hent info om hvem der skal søges på (hvem er kendt i
> medlems-db) - lægges i array (kun primær id)

Hvorfra? Hvis det er samme sted som før, kan 1 og 2 formentlig
lægges sammen.
--
Jens Gyldenkærne Clausen
Svar venligst under det du citerer, og citer kun det der er
nødvendigt for at forstå dit svar i sammenhængen. Se hvorfor og
hvordan på http://usenet.dk/netikette/citatteknik.html

Jon Klose Larsen (10-05-2005)
Kommentar
Fra : Jon Klose Larsen


Dato : 10-05-05 16:17

En lille update...

Jeg har nu omskrevet mit script, og det er nu meget hurtigere end før.
I mine foreløbige tests, så skærer det nye script ca. halvdelen af tiden som
bruges - fra 11 => 5sek.


>> 1) hent eksterne data og
>
> Hvorfra (database, application-variabel, ?)

Disse data hentes fra en tekstfil på nettet (med
"MSXML2.ServerXMLHTTP.3.0"), og opdateres af anden part (jeg har ingen som
helst mulighed for at påvirke indhold, visning eller frekvensen af disse
data - kan kun hente/læse/behandle dem)

>
>> 2) hent info om hvem der skal søges på (hvem er kendt i
>> medlems-db) - lægges i array (kun primær id)
>
> Hvorfra? Hvis det er samme sted som før, kan 1 og 2 formentlig
> lægges sammen.

Disse data ligger i min egen database. Grunden til at jeg lægger dem i en
array, er for at øge hastigheden, når jeg skal gennem dem flere gange
(regner med at denne version er hurtigere end at løbe gennem et recordset?)

Jeg har en lille test-side kørende som viser et udpluk af de log-data som
jeg opsamler og behandler....
http://www.flysim.dk/eud_cpt/satnetdata/loggerstatus.asp

Takker endnu engang for hjælpen.... nu vil jeg til at se på de mere
avancerede ting som kan/skal beregnes og logges (nu er der "overskud" til
det i script-afviklingen).

Jon



Søg
Reklame
Statistik
Spørgsmål : 177501
Tips : 31968
Nyheder : 719565
Indlæg : 6408522
Brugere : 218887

Månedens bedste
Årets bedste
Sidste års bedste