| Überblick
Ein entscheidendes Kriterium bei der Entwicklung professioneller Web-Sites stellt die Performance dar. Wer möchte die Nutzer schon gerne warten lassen oder gar mit Fehlermeldungen verschrecken? Als Flaschenhals stellen sich hierbei in den meisten Fällen die Datenbankzugriffe heraus. Arbeiten Sie mit MS Access kann es schon bei relativ wenigen gleichzeitigen Zugriffen zu Wartezeiten und Zugriffsfehlern kommen, aber selbst bei Verwendung eines leistungsfähigen DB-Servers wie MS Sql, Oracle oder Interbase können viele gleichzeitige Zugriffe schnell zu Engpässen in der Performance führen.
In den meisten Fällen werden hierbei immer wieder Daten aus den gleichen Tabellen abgerufen, sei es die Menüstruktur, eine Terminliste, das Telefonbuch oder eine komplette Produktdatenbank. Auch wir selbst verwenden auf dieser Site eine Datenbank zur Verwaltung der Kategorien (die Sie rechts sehen), der Artikel und der Autoren.
Häufig sind diese Tabellen relativ klein, d.h. sie beinhalten nur wenige (zehn)tausend Datensätze mit insgesamt wenigen MB Größe und die gewünschten Datensätze lassen sich mit Hilfe einfacher Kriterien auswählen. In diesem Fall läßt sich die Performance in einigen Fällen beträchtlich verbessern, wenn die Tabellen im Speicher des Web-Servers zwischengelagert werden.
Vorbereitung
Damit Sie die Beispiele nicht nur nachvollziehen sondern auch gleich selbst ausprobieren können, stellen wir Ihnen im Rahmen des Downloads neben den Skripten auch die verwendete Datenbank im MS Access 2000 Format zur Verfügung.
Die Datenbank besteht aus zwei Tabellen; 'PLZ' beinhaltet die deutschen Postleitzahlen und zu jeder eine zugehörige Gebietsnummer, 'Gebiete' enthält zu jeder Gebietsnummer den Namen, Kurznamen sowie das Kfz-Zeichen. Enthalten sind alle Kreise, kreisfreien Städte und teilweise auch die Stadtteile bzw. -bezirke. Die Datenbank ist zwar nicht auf dem neuesten Stand, das soll uns aber im Rahmen dieses Beispiels nicht weiter stören.
Insgesamt ist die Datenbank gut 400 kB groß und enthält ca. 800 Datensätze in der Gebietstabelle sowie gut 8.000 in der PLZ-Tabelle.
Alle Beispiele dieses Beitrages wurden in JScript erstellt, sie sind aber ingesamt recht kurz und einfach gehalten, so dass sie sich problemlos auf VBScript übertragen lassen sollten.
Disconnected recordsets
Die Recordsets von ADO sind Ihnen sicherlich bereits bekannt, um die PLZ-Tabelle unserer Datenbank abzurufen können wir in ASP zum Beispiel folgendes Codestück verwenden:
var objCon, strCon, strSqlPlz, objRSPlz;
strCon = 'Provider=Microsoft.Jet.OLEDB.4.0;Persist Security Info=False;Data Source=' + Server.MapPath('./Gebiete.mdb');
strSqlPlz = 'SELECT Plz, Gebiet FROM Plz';
objCon = Server.CreateObject('ADODB.Connection');
objCon.Open(strCon);
objRSPlz = Server.CreateObject('ADODB.Recordset');
objRSPlz.Open(strSqlPlz, objCon);
Nun werden Sie sich wahrscheinlich fragen, was 'Disconnected Recordsets' sind, wie Sie diese erzeugen und anwenden können.
Im Prinzip handelt es sich dabei um ganz normale Recordsets, der einzige Unterschied besteht darin, dass sie nach dem Abrufen der Daten von der zugehörigen Datenbankverbindung getrennt (disconnected) werden und somit auch noch nach dem Schließen der Verbindung zur Verfügung stehen.
Das ganze funktioniert nur bei Verwendung eines statischen und clientseitigen Cursors, bei Verwendung eines serverseitigen Cursors würden die Daten zu dem Zeitpunkt, an dem die Verbindung getrennt wird, ja evtl. noch gar nicht bzw. nur zum Teil auf dem Webserver vorliegen. Um das Recordset von der DB-Verbindung zu lösen, genügt es, die Eigenschaft 'ActiveConnection' auf 'nothing' zu setzen. Bedauerlichweise kennt JScript weder 'nothing' noch läßt sich 'null' ersatzweise verwenden, wir bedienen uns deshalb einer kleinen VBScript-Hilfsfunktion:
<SCRIPT LANGUAGE=VBScript RUNAT=Server>
function Disconnect(rsTmp)
set rsTmp.ActiveConnection = nothing
end function
</SCRIPT>
Nach diesem kleinen Einschub möchten wir nun aber endlich unser disconnected recordset erzeugen:
var objCon, strCon, strSqlPlz, objRSPlz;
strCon = 'Provider=Microsoft.Jet.OLEDB.4.0;Persist Security Info=False;Data Source=' + Server.MapPath('./Gebiete.mdb');
strSqlPlz = 'SELECT Plz, Gebiet FROM Plz';
objCon = Server.CreateObject('ADODB.Connection');
objCon.Open(strCon);
objRSPlz = Server.CreateObject('ADODB.Recordset');
objRSPlz.CursorType = 3;
objRSPlz.CursorLocation = 3;
objRSPlz.Open(strSqlPlz, objCon);
Disconnect(objRSPlz);
objCon.Close();
Auch nach dem Schließen der Datenbank können wir noch wie gewohnt auf das Recordset zugreifen, wir können nach Einträgen suchen, die Daten sortieren oder filtern - das folgende Beispiel gibt zur Demonstartion alle Datensätze mit Postleitzahlen zwischen 1500 und 1600 aus:
objRSPlz.Filter = 'PLZ > 1500 AND PLZ < 1600';
while (!objRSPlz.EOF){
Response.Write(objRSPlz('PLZ').Value + ': ' + objRSPlz('Gebiet').Value + '<br>');
objRSPlz.MoveNext();
}
Sie finden das komplette Beispiel im Download-Archiv unter test.asp.
Optimierung
Um eine möglichst gute Performance beim Durchsuchen oder Filtern unserer Datenmenge zu erreichen, sollten die Spalten, die hierfür als Kriterium benutzt werden, indiziert werden. Dies läßt sich sehr einfach durch Setzen der Optimize-Eigenschaft des betreffenden Feldes erreichen, fügen Sie einfach vor dem Aufruf von 'Disconnect' noch die beiden folgenden Zeilen ein:
objRSPlz(0).Properties('Optimize') = true;
objRSPlz(1).Properties('Optimize') = true;
Schön und gut werden Sie denken, was passiert aber wenn die Seite beendet wird, das Recordset wird doch zerstört - wo liegt denn da der versprochene Performancegewinn?
Sie haben natürlich recht, damit unser Recordset auch bei weiteren Aufrufen der selben oder anderer Seiten noch zur Verfügung steht, müssen wir es im Application-Objekt speichern. Wie dies geht, zeigen wir im nächsten Abschnitt. |