|
| SP: Tjekke om RecordSet er tomt Fra : Kasper Ovi |
Dato : 26-04-02 13:25 |
|
Hej
Hvis jeg f.eks. har følgende linjer, hvordan tjekker jeg så om RS er tomt:
sqlString = "SELECT * FROM IP WHERE RecipeID=" & ID
RS.Open sqlString
??
Hvis jeg f.eks. skriver:
IP = RS("IP")
får jeg en exception hvis recordsættet er tomt.
Jeg kan heller ikke bruge dette:
IF (RS.EOF AND RS.BOF) THEN
Response.Write "tomt recordset"
END IF
Jeg har overset en eller anden lille fiks ting - jeg ved bare ikke hvad!!
Hilsen
Kasper
| |
Jesper Stocholm (26-04-2002)
| Kommentar Fra : Jesper Stocholm |
Dato : 26-04-02 14:08 |
|
Kasper Ovi wrote in news:rIby8.161$pL4.2104392@news.orangenet.dk:
>
> Hvis jeg f.eks. skriver:
> IP = RS("IP")
>
> får jeg en exception hvis recordsættet er tomt.
>
ja
> Jeg kan heller ikke bruge dette:
>
> IF (RS.EOF AND RS.BOF) THEN
> Response.Write "tomt recordset"
> END IF
>
hvorfor kan du ikke det ? Hvilken fejl får du ?
> Jeg har overset en eller anden lille fiks ting - jeg ved bare ikke
> hvad!!
>
husker du at "instantiere" RS som et ADODB.Recordset ... altså
set RS = server.createobject("ADODB.Recordset")
?
.... ps: jeg fik disse tilovers, da jeg læste dit indlæg :
!!
:)
--
Jesper Stocholm
http://stocholm.dk (ikke online pt.)
http://asp.stocholm.dk (ikke online pt.)
Svar til gruppen og ikke til mig privat pr. email :|
| |
Kasper Ovi (29-04-2002)
| Kommentar Fra : Kasper Ovi |
Dato : 29-04-02 12:43 |
|
> > Jeg kan heller ikke bruge dette:
> >
> > IF (RS.EOF AND RS.BOF) THEN
> > Response.Write "tomt recordset"
> > END IF
> >
>
> hvorfor kan du ikke det ? Hvilken fejl får du ?
Jeg har fundet ud af at den fejl jeg gjorde, var at tjekke på både oef og
bof.
Jeg skulle bare have tjekket på RS.EOF - så virker det
Hilsen
Kasper
| |
Jesper Stocholm (03-05-2002)
| Kommentar Fra : Jesper Stocholm |
Dato : 03-05-02 09:41 |
|
Kasper Ovi wrote in news:nnaz8.101$Ho1.231988429@news.orangenet.dk:
>> > Jeg kan heller ikke bruge dette:
>> >
>> > IF (RS.EOF AND RS.BOF) THEN
>> > Response.Write "tomt recordset"
>> > END IF
>> >
>>
>> hvorfor kan du ikke det ? Hvilken fejl får du ?
>
> Jeg har fundet ud af at den fejl jeg gjorde, var at tjekke på både oef
> og bof.
>
> Jeg skulle bare have tjekket på RS.EOF - så virker det
>
mjaeh ... måske ...
Prøv at kigge på http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdprobof.asp
Nu kan man desværre ikke se, hvornår en givet side er ændret på
msdn.microsoft.com , men jeg vil æde min gamle hat på, at de har ændret
på beskrivelsen indenfor den sidste måned. Der er nogle overvejelser om,
hvordan man skal bruge EOF og BOF til at checke, om et recordset er tomt
eller ej. Der står bla. :
"If either the BOF or EOF property is True, there is no current record."
og
"If you open a Recordset object containing no records, the BOF and EOF
properties are set to True"
Det er ikke fordi jeg vil kne*** fluer, men det jeg vil mene, at det
at checke om der er en record, hvor cursoren nu end står, eller at checke
om et recordset er tomt, ikke er det samme ... og man kan derfor
potentielt komme ud for, at EOF returnerer TRUE ... men at der rent
faktisk er records i dit recordset. Jeg har ikke testet det, men jeg kunne
forestille mig, at man ville kunne opleve dette, hvis en SQL-forespørgsel
returnerer mere end ét recordset og man dermed skal bruge
oRec.NextRecordset til at navigere imellem disse.
Min pointe er: For at teste om et recordset er tomt, _skal_ der checkes
på både EOF of BOF. Jeg har i øvrigt ikke oplevet de problemer du
beskriver ved din anvendelse af det, og jeg checker altid på begge
properties.
:)
--
Jesper Stocholm
http://stocholm.dk
http://asp.stocholm.dk
Svar til gruppen og ikke til mig privat pr. email :|
| |
Allan Ebdrup (03-05-2002)
| Kommentar Fra : Allan Ebdrup |
Dato : 03-05-02 15:19 |
|
"Jesper Stocholm" <spam200204@stocholm.dk> wrote in message
news:Xns92036CA46CBCEspamstocholmdk@130.226.1.34...
> Det er ikke fordi jeg vil kne*** fluer, men det jeg vil mene, at det
> at checke om der er en record, hvor cursoren nu end står, eller at checke
> om et recordset er tomt, ikke er det samme ... og man kan derfor
> potentielt komme ud for, at EOF returnerer TRUE ... men at der rent
> faktisk er records i dit recordset. Jeg har ikke testet det, men jeg kunne
> forestille mig, at man ville kunne opleve dette, hvis en SQL-forespørgsel
> returnerer mere end ét recordset og man dermed skal bruge
> oRec.NextRecordset til at navigere imellem disse.
>
> Min pointe er: For at teste om et recordset er tomt, _skal_ der checkes
> på både EOF of BOF. Jeg har i øvrigt ikke oplevet de problemer du
> beskriver ved din anvendelse af det, og jeg checker altid på begge
> properties.
Hvis du bruger et clientside recordset er det vel pænere at checke på
..RecordCount=0.
At checke på både EOF og BOF er unødvendigt da et nyåbnet recordset altid
står ved første record og derfor er EOF sand hvis det er tomt (BOF er også
sand), problemerne opstår først når man genbruger et recordset flere gange,
så bør man checke på både EOF og BOF. Personligt er det meget sjældent jeg
har brug for at genbruge et recordset (fx gennemløbe det flere gange), og i
de tilfælde kommer jeg hele koden ind i en betingelse for om recordsettet
var EOF fra starten - det bliver vel et spørgsmål om personlig kode-stil.
Ligesom det også virker lidt omsonst at gennemløbe et array fra
LBound(Array) til UBound(Array) når nu LBound(Array)=0 i alle arrays
medmindre man virkeligt gør sig umage for at starte ved et andet indeks.
MVH
Allan
| |
LrsN (03-05-2002)
| Kommentar Fra : LrsN |
Dato : 03-05-02 16:27 |
|
"Allan Ebdrup" <ebdrup@ti-fire.dk> wrote in message
news:aau669$b1n$1@news.cybercity.dk...
> "Jesper Stocholm" <spam200204@stocholm.dk> wrote in message
> news:Xns92036CA46CBCEspamstocholmdk@130.226.1.34...
> > Det er ikke fordi jeg vil kne*** fluer, men det jeg vil mene, at det
> > at checke om der er en record, hvor cursoren nu end står, eller at
checke
> > om et recordset er tomt, ikke er det samme ... og man kan derfor
> > potentielt komme ud for, at EOF returnerer TRUE ... men at der rent
> > faktisk er records i dit recordset. Jeg har ikke testet det, men jeg
kunne
> > forestille mig, at man ville kunne opleve dette, hvis en
SQL-forespørgsel
> > returnerer mere end ét recordset og man dermed skal bruge
> > oRec.NextRecordset til at navigere imellem disse.
> >
> > Min pointe er: For at teste om et recordset er tomt, _skal_ der checkes
> > på både EOF of BOF. Jeg har i øvrigt ikke oplevet de problemer du
> > beskriver ved din anvendelse af det, og jeg checker altid på begge
> > properties.
>
> Hvis du bruger et clientside recordset er det vel pænere at checke på
> .RecordCount=0.
depends.....recordcount er ikke tilgængeligt hvis du har lavet dig et
forwardonly-recordset, hvilket er rimelig almidelige i webverdenen, hvor man
typisk lister data der allerede er sorteret i forespørgslen da man ikke vil
omsortere i ASP, og dermed i teorien sparer lidt arbejde for recordsettet.
> At checke på både EOF og BOF er unødvendigt da et nyåbnet recordset altid
> står ved første record og derfor er EOF sand hvis det er tomt (BOF er også
> sand),
Enig, så et tjek på .EOF må være rigeligt. Eksempler på at det kan fucke op
hvis ikke der tjekkes på BOF vil jeg gerne se.... er der nogen der har nogle
eksempler???
>problemerne opstår først når man genbruger et recordset flere gange,
> så bør man checke på både EOF og BOF. Personligt er det meget sjældent jeg
> har brug for at genbruge et recordset (fx gennemløbe det flere gange), og
i
> de tilfælde kommer jeg hele koden ind i en betingelse for om recordsettet
> var EOF fra starten
me2
> Ligesom det også virker lidt omsonst at gennemløbe et array fra
> LBound(Array) til UBound(Array) når nu LBound(Array)=0 i alle arrays
> medmindre man virkeligt gør sig umage for at starte ved et andet indeks.
errrrrhh uenig!
Jeg vil klart hellere have at koden virker så mange steder som muligt og er
generisk! du kan ikke være sikker på hvilken mode en maskine kører i... Det
er efter min overbevisning det samme som 'bare' at bruge datoer som
#12/03/02" når man har datoer... Det virker godt nok lige nu og her, men
giver en fandens ballade hvis der bliver lavet noget om på systemet, eller
hvis koden skal flyttes til en anden maskine.
/Jesper
| |
Allan Ebdrup (03-05-2002)
| Kommentar Fra : Allan Ebdrup |
Dato : 03-05-02 17:32 |
|
"LrsN" <jesper@L.arsen.spamstinker.dk> wrote in message
news:N_xA8.8$274.217@news010.worldonline.dk...
>
> "Allan Ebdrup" <ebdrup@ti-fire.dk> wrote in message
> news:aau669$b1n$1@news.cybercity.dk...
[KLIP - check om recordset er tomt]
> > Hvis du bruger et clientside recordset er det vel pænere at checke på
> > .RecordCount=0.
> depends.....recordcount er ikke tilgængeligt hvis du har lavet dig et
> forwardonly-recordset, hvilket er rimelig almidelige i webverdenen, hvor
man
> typisk lister data der allerede er sorteret i forespørgslen da man ikke
vil
> omsortere i ASP, og dermed i teorien sparer lidt arbejde for recordsettet.
Recordcount er tilgængelig hvis du bruger et clientside recordset som er det
bedste for performance med små recordsets eller recordsets du alligevel skal
løbe hele vejen igennem. Det er netop almindeligt i webverdenen. (Du lukker
databaseforbindelsen hurtigt med en clientside cursor)
se:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/
mdrefodbcprovspec.asp
[klip]
> > Ligesom det også virker lidt omsonst at gennemløbe et array fra
> > LBound(Array) til UBound(Array) når nu LBound(Array)=0 i alle arrays
> > medmindre man virkeligt gør sig umage for at starte ved et andet indeks.
> errrrrhh uenig!
> Jeg vil klart hellere have at koden virker så mange steder som muligt og
er
> generisk! du kan ikke være sikker på hvilken mode en maskine kører i...
Det
> er efter min overbevisning det samme som 'bare' at bruge datoer som
> #12/03/02" når man har datoer... Det virker godt nok lige nu og her, men
> giver en fandens ballade hvis der bliver lavet noget om på systemet, eller
> hvis koden skal flyttes til en anden maskine.
Hvis du har sagt A må du også sige B, hvis du på den ene installation kan
finde på at ændre på at arrays er 0-indekseret, kan du også finde på at
ændre på at EOF er sand hvis recordsettet er tomt.
MVH
Allan
| |
Jakob Andersen (03-05-2002)
| Kommentar Fra : Jakob Andersen |
Dato : 03-05-02 18:48 |
|
"Allan Ebdrup" <ebdrup@ti-fire.dk> wrote in message
news:aaudv0$l1s$1@news.cybercity.dk...
> Recordcount er tilgængelig hvis du bruger et clientside recordset som er
det
> bedste for performance med små recordsets eller recordsets du alligevel
skal
> løbe hele vejen igennem.
Det hurtigste er da at bruge en ForwardOnly cursor. Og med denne er
RecordCount ikke tilfængelig.
Hvis du ikke mener at ForwardOnly er hurtigst vil jeg meget gerne se en
lille test af hastighederne.
--
Jakob Andersen
| |
LrsN (03-05-2002)
| Kommentar Fra : LrsN |
Dato : 03-05-02 19:19 |
|
> Recordcount er tilgængelig hvis du bruger et clientside recordset som er
det
> bedste for performance med små recordsets eller recordsets du alligevel
skal
> løbe hele vejen igennem. Det er netop almindeligt i webverdenen. (Du
lukker
> databaseforbindelsen hurtigt med en clientside cursor)
Jeg ville skrive det før men gad ikke hmmm. det link jeg fik..... prøv
lige at se om du kan finde noget om EOF... hvorfor er der ikke noget om den
egenskab... nå: Jeg kan godt se at det virker tit. Mon ikke det bare er
noget med at du ikke styrer dine egenskaber ved de recordsets du åbner nok??
For hvis man lurer lidt på recordcout-propertien for de selvsamme recordsets
ses at:
<citat>
The cursor type of the Recordset object affects whether the number of
records can be determined. The RecordCount property will return -1 for a
forward-only cursor; the actual count for a static or keyset cursor; and
either -1 or the actual count for a dynamic cursor, depending on the data
source.
</citat>
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/
mdprorecordcount.asp
godtså...
> Hvis du har sagt A må du også sige B, hvis du på den ene installation kan
> finde på at ændre på at arrays er 0-indekseret, kan du også finde på at
> ændre på at EOF er sand hvis recordsettet er tomt.
Hvordan søren (og hvorfor) gør man det? Det har jeg aldrig set i nogen
implementationer eller guides. (forespurgte iøvrigt også på dette i min
sidste posting, om der var nogen der havde et eksempel på hvordan det kunne
fucke op....har du et eksempel vil jeg da gerne se det, clientside, ikke
genbrugeligt naturligvis..). Derimod har jeg set masser af eksempler hvor
folk synes det er skægt at have OPTION BASE=1 .... fordi...... ja fordi...
tror jeg!
/Jesper
| |
LrsN (03-05-2002)
| Kommentar Fra : LrsN |
Dato : 03-05-02 20:24 |
|
>
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/
> mdprorecordcount.asp
..... nå. Jeg testede lige for skægt med alle kombier af cursorType og
cursorLoc. Her er hvad der kom ud af dette script (VB..)
For clEnum = 2 To 3 '* 2 =server 3 = client
For ctenum = 0 To 3
With rs
.CursorLocation = clEnum
.CursorType = ctenum
.Source = sql
.ActiveConnection = con
.Open
End With
Debug.Print "rc:" & rs.RecordCount & ": cT:" & ctenum & " ActualcT:"
& rs.CursorType & " cL:" & clEnum
rs.Close
Next
Next
rc:-1: cT:0 ActualcT:0 cL:2
rc:12: cT:1 ActualcT:1 cL:2
rc:-1: cT:2 ActualcT:2 cL:2
rc:12: cT:3 ActualcT:3 cL:2
rc:12: cT:0 ActualcT:3 cL:3
rc:12: cT:1 ActualcT:3 cL:3
rc:12: cT:2 ActualcT:3 cL:3
rc:12: cT:3 ActualcT:3 cL:3
Man kan jo sige at Allan har rimelig ret i at på clientside-recordsets duer
..recordcount! da de af en eller anden grund ikke gider høre efter den type
man prøver at sætte den i!
Jeg testede med
oledb -> access
oledb -> msSqlsvr
oledb -> odbc, og det var det samme over det hele
/J
| |
Jakob Andersen (03-05-2002)
| Kommentar Fra : Jakob Andersen |
Dato : 03-05-02 22:19 |
|
"LrsN" <jesper@L.arsen.spamstinker.dk> wrote in message
news:5tBA8.58$274.13079@news010.worldonline.dk...
> Man kan jo sige at Allan har rimelig ret i at på clientside-recordsets
duer
> .recordcount!
Og jeg lavede så ligge samme test med en tidsfaktor i også, og der ser
resultatet sådan her ud (Som i kan se er det 4600 records fra en
nyhedsdatabase der "danses" med):
------------------------------------
CursorLocation er sat til Server
CursorType: Sat til Forward only cursor ( Er Forward only)
RecordCount: -1
Tid for gennemløbning af records : 7,015625
-----------------------------------
CursorLocation er sat til Server
CursorType: Sat til Keyset cursor ( Er Keyset)
RecordCount: 4600
Tid for gennemløbning af records : 41,8125
-----------------------------------
CursorLocation er sat til Server
CursorType: Sat til Dynamic cursor ( Er Dynamic)
RecordCount: -1
Tid for gennemløbning af records : 39,85938
-----------------------------------
CursorLocation er sat til Server
CursorType: Sat til Static cursor ( Er Static)
RecordCount: 4600
Tid for gennemløbning af records : 28,90625
-----------------------------------
CursorLocation er sat til Client
CursorType: Sat til Forward only cursor ( Er Static)
RecordCount: 4600
Tid for gennemløbning af records : 2,070313
-----------------------------------
CursorLocation er sat til Client
CursorType: Sat til Keyset cursor ( Er Static)
RecordCount: 4600
Tid for gennemløbning af records : 2,09375
-----------------------------------
CursorLocation er sat til Client
CursorType: Sat til Dynamic cursor ( Er Static)
RecordCount: 4600
Tid for gennemløbning af records : 2,203125
-----------------------------------
CursorLocation er sat til Client
CursorType: Sat til Static cursor ( Er Static)
RecordCount: 4600
Tid for gennemløbning af records : 2,101563
-----------------------------------
Og det foregik med et script ala dette:
Dim arrCursorLocations(1)
arrCursorLocations(0) = "Server"
arrCursorLocations(1) = "Client"
Dim arrCursorType(3)
arrCursorType(0) = "Forward only"
arrCursorType(1) = "Keyset"
arrCursorType(2) = "Dynamic"
arrCursorType(3) = "Static"
For iCursorLocation = 2 To 3
For iCursorType = 0 To 3
With objRS
.CursorLocation = iCursorLocation
.CursorType = iCursorType
.Source = "SELECT Overskrift, Tekst FROM tblNyheder"
.ActiveConnection = objConn
.Open
End With
Response.Write( "CursorLocation er sat til " )
Response.Write( arrCursorLocations( iCursorLocation - 2 ) )
Response.Write( "<br />" )
Response.Write( "CursorType er sat til " & arrCursorType( iCursorType ) )
Response.Write( " (<b>Er " )
Response.Write( arrCursorType( objRS.CursorType ) )
Response.Write( "</b>)" )
Response.Write( "<br />" )
Response.Write( "RecordCount: " & objRS.RecordCount & "<br />")
startTid = Timer
Do while Not objRS.EOF
Testvar = objRS( "Overskrift" ) & "<br />" & objRS( "Tekst")
objRS.Movenext
Loop
Response.Write("Tid for gennemløbning af records : " )
Response.Write( Timer - startTid & "<br />")
Response.Write( "-----------------------<br />" )
objRS.Close
Next
Next
Jeg må sige jeg er lidt overrasket over forskellen i hastigheden af
gennemløbning
--
Jakob Andersen
| |
Peter Lykkegaard (04-05-2002)
| Kommentar Fra : Peter Lykkegaard |
Dato : 04-05-02 13:45 |
|
"Jakob Andersen" <jakob@effectus.dk> wrote in message
news:aauur8$1bkn$1@news.cybercity.dk...
> Jeg må sige jeg er lidt overrasket over forskellen i hastigheden af
> gennemløbning
Synd at du ikke tager i betragtning hvor lang tid de enkelte typer er om at
åbne
Anyways, hvis man dribler forbi www.4guysfromrolla.com så vil man kunne
finde indtil flere artikler om effektiv brug af recordets
mvh/Peter Lykkegaard
| |
Jakob Andersen (04-05-2002)
| Kommentar Fra : Jakob Andersen |
Dato : 04-05-02 17:48 |
|
"Peter Lykkegaard" <polonline@hotmail.com> wrote in message
news:3cd3d783$0$78759$edfadb0f@dspool01.news.tele.dk...
> Synd at du ikke tager i betragtning hvor lang tid de enkelte typer er om
at
> åbne
Sådan her:
CursorLocation er sat til Server
CursorType er sat til Forward only (Er Forward only)
RecordCount: -1
Tid for åbning af recordset : 0,1328125
Tid for gennemløbning af records : 1,5625
Tid ialt: 1,695313
-----------------------
CursorLocation er sat til Server
CursorType er sat til Keyset (Er Keyset)
RecordCount: 1000
Tid for åbning af recordset : 0,0703125
Tid for gennemløbning af records : 9,1875
Tid ialt: 9,257813
-----------------------
CursorLocation er sat til Server
CursorType er sat til Dynamic (Er Keyset)
RecordCount: -1
Tid for åbning af recordset : 0,0703125
Tid for gennemløbning af records : 8,367188
Tid ialt: 8,4375
-----------------------
CursorLocation er sat til Server
CursorType er sat til Static (Er Static)
RecordCount: 1000
Tid for åbning af recordset : 0,6015625
Tid for gennemløbning af records : 6,1875
Tid ialt: 6,789063
-----------------------
CursorLocation er sat til Client
CursorType er sat til Forward only (Er Static)
RecordCount: 1000
Tid for åbning af recordset : 1,476563
Tid for gennemløbning af records : 0,4765625
Tid ialt: 1,953125
-----------------------
CursorLocation er sat til Client
CursorType er sat til Keyset (Er Static)
RecordCount: 1000
Tid for åbning af recordset : 1,546875
Tid for gennemløbning af records : 0,4765625
Tid ialt: 2,023438
-----------------------
CursorLocation er sat til Client
CursorType er sat til Dynamic (Er Static)
RecordCount: 1000
Tid for åbning af recordset : 1,648438
Tid for gennemløbning af records : 0,4765625
Tid ialt: 2,125
-----------------------
CursorLocation er sat til Client
CursorType er sat til Static (Er Static)
RecordCount: 1000
Tid for åbning af recordset : 1,609375
Tid for gennemløbning af records : 0,4765625
Tid ialt: 2,085938
-----------------------
Under kørsel af dette script må jeg åbenbart ikke få lov til at benytte en
dynamic cursor, hvilket jeg syntes er lidt mystisk.
> Anyways, hvis man dribler forbi www.4guysfromrolla.com så vil man kunne
> finde indtil flere artikler om effektiv brug af recordets
Det kan godt være det er mig, men mange af 4Guys artikler om ADO manler
ligesom konklusionen.
--
Jakob Andersen
| |
Allan Ebdrup (04-05-2002)
| Kommentar Fra : Allan Ebdrup |
Dato : 04-05-02 19:40 |
|
"Jakob Andersen" <jakob@effectus.dk> wrote in message
news:ab13c6$s9t$1@news.cybercity.dk...
> "Peter Lykkegaard" <polonline@hotmail.com> wrote in message
> news:3cd3d783$0$78759$edfadb0f@dspool01.news.tele.dk...
> > Synd at du ikke tager i betragtning hvor lang tid de enkelte typer er om
> at
> > åbne
>
> Sådan her:
[klip - kode til at teste cursors og type for recordset]
Min påstand: Da det oftest er databaseserveren der sætter dagsordenen for
hvor hurtigt dine sider kører, gælder det altid om at lukke sine connections
så hurtigt som muligt. Dette gør du mest effektivt med en clientside cursor.
(som sagt gælder dette specielt hvis man skal løbe gennem alle tuplerne, og
hvis man ikke vil gennemløbe alle tuplerne kunne man sikkert forbedre din
forespørgsel så man kun får de tupler der skal bruges).
Ang. din test:
Der er forskel på performance og scaleability, selvom performance hænger
delvist sammen med scaleability.
Det interresante for webapplikationer er scaleability, hvis der er problemer
med performance vil scaleability alligevel være forfærdentlig, mens god
scaleability har som mål at der skal være god performance på de enkelte
sidevisninger. God scaleability er derfor meget sværere at opnå end god
performance.
Hvis du vil måle scaleability skal du belaste serveren med forespørgsler så
de bliver behandlet parallelt i forskellige tråde. Til det skal man bruge et
værktøj som Microsoft Web Application Stress (WAS):
http://homer.rte.microsoft.com/
Se fx artiklen: "Server Performance and Scalability Killers"
http://msdn.microsoft.com/library/default.asp?URL=/library/en-us/dniis/html/
tencom.asp
Under punktet "Thou shalt use single-client, single-request testing." står
der bla.:
"A common mistake for people writing ASP and ISAPI applications is to test
their applications by using a single browser."
Under punktet "Thou shalt not use real-world scenarios." står der bla.:
"It's easy to fall into the trap of tuning your application for a few
specific, artificial scenarios (such as benchmarks)."
Og det du har lavet er et benchmark. Givet, det er et relevant benchmark,
der er godt til at lave nogle tommelfingerregler udfra, men du bør under
alle omstændigheder lave testen med WAS hvis du vil sige noget om
scaleability i stedet for performance, og pas på med at tro det altid gælder
der vil altid være scenarier du ikke har taget højde for (Murphey vil give
mig ret).
MVH
Allan Ebdrup
P.S. Som sagt er .RecordCount tilgængeligt på et forwardonly recordset med
en clientside cursor (hvilket også fremgik af artiklen jeg linkede til .
| |
Jakob Andersen (04-05-2002)
| Kommentar Fra : Jakob Andersen |
Dato : 04-05-02 19:47 |
|
"Allan Ebdrup" <ebdrup@ti-fire.dk> wrote in message
news:ab19qq$14om$1@news.cybercity.dk...
> Hvis du vil måle scaleability skal du belaste serveren med forespørgsler
så
> de bliver behandlet parallelt i forskellige tråde. Til det skal man bruge
et
> værktøj som Microsoft Web Application Stress (WAS):
> http://homer.rte.microsoft.com/
Jeg kender godt MS WAS og har brugt det flittigt i mange sammenhænge men jeg
må dog indrømme at jeg ikke lige har brugt det i denne sammenhæng. Men det
vigtigste er vel oftest at man hurtigst muligt får klaret sine forretninger
med databasen og så væk igen. Og flere klienter ændrer vel ikke på opførslen
af en cursor, eller hvad?
> P.S. Som sagt er .RecordCount tilgængeligt på et forwardonly recordset med
> en clientside cursor (hvilket også fremgik af artiklen jeg linkede til
.
Men reelt bruges der jo ikke en ForwardOnly cursor men en Static eller er
det blot min CursorType property der ikke vil læses korrekt?
--
Jakob Andersen
| |
Allan Ebdrup (04-05-2002)
| Kommentar Fra : Allan Ebdrup |
Dato : 04-05-02 21:48 |
|
"Jakob Andersen" <jakob@effectus.dk> wrote in message
news:ab1abi$15ft$1@news.cybercity.dk...
> "Allan Ebdrup" <ebdrup@ti-fire.dk> wrote in message
> news:ab19qq$14om$1@news.cybercity.dk...
> > Hvis du vil måle scaleability skal du belaste serveren med forespørgsler
> så
> > de bliver behandlet parallelt i forskellige tråde. Til det skal man
bruge
> et
> > værktøj som Microsoft Web Application Stress (WAS):
> > http://homer.rte.microsoft.com/
>
>
> Jeg kender godt MS WAS og har brugt det flittigt i mange sammenhænge men
jeg
> må dog indrømme at jeg ikke lige har brugt det i denne sammenhæng. Men det
> vigtigste er vel oftest at man hurtigst muligt får klaret sine
forretninger
> med databasen og så væk igen. Og flere klienter ændrer vel ikke på
opførslen
> af en cursor, eller hvad?
Uden brug af WAS kan ikke se effekten af, at du med et serverside recordset
har databaseforbindelsen åben indtil du er helt færdig med at løbe gennem
dit recordset, mens du med et clientside recordset kan sætte
..Activeconnection = Nothing lige efter du har eksekveret dit SQL/SPROC kald,
og derfor have frigivet din connection mens du behandler de data du har
trukket ud af databasen. Det giver en forskel for scaleability, og det er
her fårene vil blive skildt fra bukkene.
> > P.S. Som sagt er .RecordCount tilgængeligt på et forwardonly recordset
med
> > en clientside cursor (hvilket også fremgik af artiklen jeg linkede til
> .
>
> Men reelt bruges der jo ikke en ForwardOnly cursor men en Static eller er
> det blot min CursorType property der ikke vil læses korrekt?
Ahh, ja det er muligt, kan man lave en .MovePrevious selvom man har
specificeret at CursorType skal være ForwardOnly? Det trode jeg nemligt ikke
man kunne (hvis der ikke er forskel er det også underligt at der er forskel
på hastigheden med et clientside recordset med hhv ForwardOnly og Static
cursor i din test, men det er måske bare et udslag for hvor stor
usikkerheden er?).
I så fald bliver en konsekvens af min påstand at en ForwardOnly cursor ikke
giver den bedste scaleability - det der er vigtigt er at man bruger et
clientside recordset. Dette er selvfølgeligt kun en tommelfingerregel men
den gælder ofte (skal vi sige i 90% af alle queries).
Se konklusionen i Nile eksemplet på MSDN:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnile/html
/docu2kbench.asp
Der står bla. :
--------------
- Use stateless database operations and always use disconnected recordsets.
- Use proper ADO coding techniques (see the FMStocks 2000 and Nile samples
on MSDN):
rs.CursorLocation = adUseClient
rs.Open cmd, , adOpenForwardOnly, adLockReadOnly
--------------
MVH
Allan
| |
Jakob Andersen (04-05-2002)
| Kommentar Fra : Jakob Andersen |
Dato : 04-05-02 23:15 |
|
"Allan Ebdrup" <ebdrup@ti-fire.dk> wrote in message
news:ab1hai$1dtb$1@news.cybercity.dk...
> Uden brug af WAS kan ikke se effekten af, at du med et serverside
recordset
> har databaseforbindelsen åben indtil du er helt færdig med at løbe gennem
> dit recordset, mens du med et clientside recordset kan sætte
Jeg er nok ude i at argumentere bare for diskussionens skyld dvs. jeg
har forstået at det er mest hensigsmæssigt at bruge en clientside cursor i
de fleste queries.
Men når det angår scalability kan man forestille sig situationer hvor
flaskehalsen ligger i netværketsforbindelsen mellem webservere og MSSQL
cluster og her vil det jo være kritisk med en clientsidecursor som belaster
forbindelse i store kortvarige peaks, dermed vil man med mange simultane
brugere opleve at der kan gå lang tid før man har fået hentet alle data fra
databasen til recordsettet hvorimod det vil blive hentet "ved brug" med en
serverside cursor og dermed mindske belastningen på netværksforbindelsen.
--
Jakob Andersen
| |
Allan Ebdrup (04-05-2002)
| Kommentar Fra : Allan Ebdrup |
Dato : 04-05-02 23:54 |
|
"Jakob Andersen" <jakob@effectus.dk> wrote in message
news:ab1mgb$1llp$1@news.cybercity.dk...
> "Allan Ebdrup" <ebdrup@ti-fire.dk> wrote in message
> news:ab1hai$1dtb$1@news.cybercity.dk...
> > Uden brug af WAS kan ikke se effekten af, at du med et serverside
> recordset
> > har databaseforbindelsen åben indtil du er helt færdig med at løbe
gennem
> > dit recordset, mens du med et clientside recordset kan sætte
>
> Jeg er nok ude i at argumentere bare for diskussionens skyld dvs. jeg
> har forstået at det er mest hensigsmæssigt at bruge en clientside cursor i
> de fleste queries.
>
> Men når det angår scalability kan man forestille sig situationer hvor
> flaskehalsen ligger i netværketsforbindelsen mellem webservere og MSSQL
> cluster og her vil det jo være kritisk med en clientsidecursor som
belaster
> forbindelse i store kortvarige peaks, dermed vil man med mange simultane
> brugere opleve at der kan gå lang tid før man har fået hentet alle data
fra
> databasen til recordsettet hvorimod det vil blive hentet "ved brug" med en
> serverside cursor og dermed mindske belastningen på netværksforbindelsen.
Det er rart at diskutere ting igennem, så lærer man altid noget (fx var jeg
ikke klar over at man blev tvunget til at bruge en static cursor når man
bruger et clientside recordset - det må jeg selv undersøge nærmere)
Som jeg har nævnt er jeg enig i at man altid skal betragte rådet om
clientside recordsets som en tommelfingerregel og teste realworld
performance og tweaks med et værktøj som WAS.
Ang. netværksflaskehals:
Hvis du løber gennem hele recordsettet bliver den samlede trafik alligevel
mindst lige så stor med er serverside recordset (sikkert lidt større, da du
skal spørge om næste pakke engang imellem osv.), den eneste forskel vil være
at du ikke har så mange databaseforbindelser åbne på samme tid, og de koster
faktisk ret meget at holde åbne. Jeg har aldrig hørt om at netværket var en
flaskehals for en MSSQL cluster der servicerer webapplikationer, næsten alt
det data der overføres skal jo sendes til klienterne, og du kan sende MEGET
data over 2 stk. 100Mbs netkort (eller måske 1Gbs netkort . Hvis der
endeligt var en flaskehals i netværket ville det næppe være noget større
problem og knalde et ekstra netkort i.
MVH
Allan
| |
Allan Ebdrup (04-05-2002)
| Kommentar Fra : Allan Ebdrup |
Dato : 04-05-02 20:14 |
|
"LrsN" <jesper@L.arsen.spamstinker.dk> wrote in message
news:3wAA8.48$274.9581@news010.worldonline.dk...
> > Recordcount er tilgængelig hvis du bruger et clientside recordset som er
> det
> > bedste for performance med små recordsets eller recordsets du alligevel
> skal
> > løbe hele vejen igennem. Det er netop almindeligt i webverdenen. (Du
> lukker
> > databaseforbindelsen hurtigt med en clientside cursor)
> Jeg ville skrive det før men gad ikke hmmm. det link jeg fik..... prøv
> lige at se om du kan finde noget om EOF... hvorfor er der ikke noget om
den
> egenskab... nå: Jeg kan godt se at det virker tit. Mon ikke det bare er
> noget med at du ikke styrer dine egenskaber ved de recordsets du åbner
nok??
> For hvis man lurer lidt på recordcout-propertien for de selvsamme
recordsets
> ses at:
> <citat>
> The cursor type of the Recordset object affects whether the number of
> records can be determined. The RecordCount property will return -1 for a
> forward-only cursor; the actual count for a static or keyset cursor; and
> either -1 or the actual count for a dynamic cursor, depending on the data
> source.
> </citat>
>
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/
> mdprorecordcount.asp
>
> godtså...
Jammen så er der jo en fejl i MS'es dokumentation eller også snakkes der kun
om serverside recordsets. Med et clientside recordset er .RecordCount
tilgængelig. Det kan du bla. se i Jacobs test. (jeg har mailet til MS om
dette og skal nok skrive her når de svarer)
godså...
> > Hvis du har sagt A må du også sige B, hvis du på den ene installation
kan
> > finde på at ændre på at arrays er 0-indekseret, kan du også finde på at
> > ændre på at EOF er sand hvis recordsettet er tomt.
>
> Hvordan søren (og hvorfor) gør man det? Det har jeg aldrig set i nogen
> implementationer eller guides. (forespurgte iøvrigt også på dette i min
> sidste posting, om der var nogen der havde et eksempel på hvordan det
kunne
> fucke op....har du et eksempel vil jeg da gerne se det, clientside, ikke
> genbrugeligt naturligvis..). Derimod har jeg set masser af eksempler hvor
> folk synes det er skægt at have OPTION BASE=1 .... fordi...... ja fordi...
> tror jeg!
Tja, du gør det fx hvis du har en funktion der tager et recordset som en
parameter, og det vil du ofte have hvis du laver en pæn seperation mellem
datatilgang, forretningslogik og præsentationslogik (gerne flere lag:
N-Tier).
Du kan ikke vide om der er "leget" med recordsettet før du får det ind (fx
er det blevet gennemløbet først) og så kan det være det indeholder records
men EOF er sand.
På samme måde bør du også bruge LBound og UBound til at gennemløbe arrays
hvis du vil være sikker på at din funktion virker selvom en anden person,
der ikke bruger 0-indekserede arrays, benytter den. (Som du så også gør).
Argumentet i begge tilfælde er at du ikke helt ved hvad din variabel
indeholder og derfor bør tage højde for dette, eller også kan du kræve
0-indekserede arrays og at recordsets altid skal stå ved første record,
begge dele er muligt bare man dokumenterer det. Jeg mener ikke der er
endegyldige tekniske argumenter for det ene eller det andet og så bliver det
et spørgsmål om personlig stil .
MVH
Allan
| |
Jakob Andersen (04-05-2002)
| Kommentar Fra : Jakob Andersen |
Dato : 04-05-02 20:32 |
|
"Allan Ebdrup" <ebdrup@ti-fire.dk> wrote in message
news:ab1bqk$171p$1@news.cybercity.dk...
>Det kan du bla. se i Jacobs test. (jeg har mailet til MS om
> dette og skal nok skrive her når de svarer)
> godså...
Det skal lige siges at det var Jesper det lavede en test, jeg byggede bare
lidt videre så vi fik tidsperspektivet ind i det.
--
Jakob Andersen
| |
|
|