Data ophalen met Getrows
Door Charles Carroll
10 november 2000
Er zijn verschillende manieren om gegevens uit een database te halen. Veel mensen gebruiken
code die er min of meer als volgt uit ziet:
'database openen
'recordset openen
Do Until rs.Eof
strAdres = rs("Adres")
strPcode = rs("Postcode")
strPlaats = rs("Woonplaats")
'meer operaties
rs.MoveNext
Loop
'recordset sluiten
'database sluiten
Hoewel dit zeker werkt, is dit niet de meest efficiënte manier. Stel dat er 500 records
in de recordset zitten met elk 3 velden, dan zou dit 1500 data aanvragen aan de database
betekenen.
...nou ja, zo dramatisch is het niet, maar wel belangrijk om te zien dat dit problemen op kan
leveren. Wat er eigenlijk gebeurt is dat er telkens een aantal records tegelijk wordt opgehaald.
Hoeveel er tegelijk worden opgehaald, kan bepaald worden met rs.CacheSize. Zou je CacheSize op 50
zetten, dan worden de records in 10 aanvragen uit de database gehaald. Bij het opvragen van het
eerste record worden records 1 tot en met 50 opgehaald. Zodra met MoveNext record 51 bereikt
is, worden de volgende 50 opgehaald.
Een ander probleem met recordsets is dat terwijl je door een recordset heen loopt, de connectie
met de database open blijft. Deze connectie is echter "duur", omdat er maar een beperkt aantal
connecties bechikbaar is en deze ook extra geheugen kost. Het zou dus veel beter zijn om alle
records in een keer op te halen, de database te sluiten en dan pas operaties op de gegevens
uit te voeren.
De onderstaande code lost deze twee grote 'problemen' op.
'database openen
'recordset openen
MyArray = rs.GetRows
'recordset sluiten
'database sluiten
NumFields = UBound(MyArray, 1)
NumRows = UBound(MyArray, 2)
For i = 0 To NumRows
strAdres = MyArray(0, i)
strPcode = MyArray(1, i)
strPlaats = MyArray(2, i)
'meer operaties
Next
De bovenstaande code opent een database en een recordset en zet met de GetRows methode alle
gegevens in een array, waarna de recordset en database gesloten worden. De array is een lokale
variabele en kan dus makkelijk gemanipuleerd worden. Hiervoor hoeft niet telkens een aanvraag
naar de database te gaan.
De rest van de code doet in feite hetzelfde als de eerdere code.
Oude gewoonten...
De meest voorkomende reden waarom mensen MoveNext gebruiken is omdat ze het zo geleerd hebben.
Maar stel je nu eens voor dat 300 mensen tegelijk op een pagina komen met database operaties.
Zonder GetRows of GetString zou er een veel zwaardere processor nodig zijn, omdat de scripts
uitgevoerd worden in round-robin en hun context en data vaak moeten worden opgeslagen
om alle aanvragen tegelijkertijd te kunnen afhandelen. Op een webserver wordt elke milliseconde
die je verspilt vermenigvuldigd door mogelijk tienduizenden gebruikers (amazon.com, cnn.com).
Je moet dus niet meer denken in traditionele een-voor-een operaties zoals MoveNext en operaties
gebruiken die vele malen sneller zijn.
Zoals je kunt zien in het GetRows voorbeeld, kun je de recordset en de database connectie sluiten
voordat je de data gaat gebruiken, bijvoorbeeld het doorlopen van de data en deze opmaken met
een loop. Stel je voor dat het lezen van gegevens 1,5 seconde duurt en het opmaken van de
gegevens 2,5 seconde, dan is de database 4 seconde geopend. Met GetRows duurt het lezen korter
(door alles in één keer op te halen), misschien maar 0.75 seconde, waarna de
recordset en de connectie gesloten zijn en teruggegeven worden aan de 'pool', voor een andere
scripts om te gebruiken. Tijdens het opmaken van de gegevens zijn er bovendien geen locks die
andere gebruikers in de weg zouden kunnen zitten.
Kyle Dyer schreef me... "Hoe zit het met Jscript?"
Hij was ook zo vriendelijk om me de resultaten van zijn research te sturen:
strSQL = "SELECT times FROM ...";
rs.Open(strSQL, conn);
recordSet.GetString(2,-1,"kolom-scheiding","rij-scheiding","null");
Parameters:
- string formaat: moet 2 zijn (verplicht in JScript)
- aantal rijen: -1 haalt ze allemaal (verplicht in JScript)
- scheiding tussen kolommen
- scheiding tussen rijen
- waarde voor 'null' waardes
Maakt het uit met kleine hoeveelheden gegevens?
JA!!!!!!!!
De SQL Server scripts op www.learnasp.com
zijn razend snel. Ooit moest ik een listbox vullen met 9 items uit een Access database.
Met MoveNext kreeg ik af en toe 90 seconden script-timeouts, terwijl GetString altijd
werkte.
Het is dus mogelijk om 'zwakke' databases (zoals Access) te gebruiken op productie
omgevingen met GetRows of GetString. Logischerwijs vermindert het de last op hoogwaardige
database back-ends zoals SQL Server en Oracle, zodat voor deze ook minder extra geheugen
en indexen nodig zijn.
Is er een snellere manier om gegevens op te halen?
Kijk eens naar "The Worlds Fastest Listbox",
de enige manier om gegevens nog sneller op te halen.
© Charles Carroll
(vertaling copyright ASPNL)
|