ASP Abfrage an AccessDB zu langsam

painkiller

Grünschnabel
Hi,

ich hab eine Acces97 Datenbank die gerademal 400kb hat. es handelt sich um ein Telefonbuch. leider sind die abfragen extrem langsam (etwa 5-10s).

die Datenbank hab ich schon repariert, komprimiert und analysiert - aber leider ohne nennenswerte Ergebnisse.

hier der Code - kann man da nochwas besser machen? es wird nur abgefragt nix geupdateed oder so...
-------------------------------------------------------------------------------------------------------------
<html>

<head>
<<title>Telefonbuch</title>
<base target="_self">
<basefont face="Arial">
</head>

<body style="padding-left: 35; padding-right: 35">

<p><img border="0" src="../bilder/ueberschrift_telefonbuch.gif" width="400" height="100"></p>


<%
'Datenbank öffnen
strConnection = "Driver={Microsoft Access Driver (*.mdb)};DBQ="
strConnection = strConnection & Server.MapPath("mdb/db2_2000.mdb")
strConnection = strConnection & ";DriverId=25;FIL=MS Access;MaxBufferSize=4096;PageTimeout=10;"
Set db = Server.CreateObject("ADODB.Connection")
db.Open strConnection

SQL = "SELECT Amt.Amt, Telefonliste.Name, Telefonliste.Vorname, Telefonliste.Standort, Telefonliste.Telefon, Telefonliste.Zimmer, Amt.Amtsnummer FROM Amt INNER JOIN Telefonliste ON Amt.AmtID = Telefonliste.AmtID WHERE Telefonliste.Name like '"&Request.QueryString("suche")&"%'or Telefonliste.Vorname like '"&Request.QueryString("suche")&"%'or Telefonliste.Telefon like '"&Request.QueryString("suche")&"%'or Amt.Amt like '"&Request.QueryString("suche")&"%'or Telefonliste.Zimmer like '"&Request.QueryString("suche")&"%'or Telefonliste.standort like '"&Request.QueryString("suche")&"%'or Amt.Amtsnummer like '"&Request.QueryString("suche")&"%' ORDER by "&Request.QueryString("b")

set rs = db.Execute(sql)
%>

<p align="left"><font face="Arial"><a href="telefonbuch.html"><b>neue Suche<br>
</b></a>&nbsp;</font></p>
<div align="left">
<table border="1" cellspacing="1" width="90%">
<tr>
<td width="163" height="25" align="left" bgcolor="#C0C0C0" valign="top"><font face="Arial" size="3"><b>Nachname</b></font></td>
<td width="123" height="25" align="left" bgcolor="#C0C0C0" valign="top"><font face="Arial" size="3"><b>Vorname</b></font></td>
<td width="212" height="25" align="left" bgcolor="#C0C0C0" valign="top"><font face="Arial" size="3"><b>Fachamt</b></font></td>
<td width="91" height="25" align="left" bgcolor="#C0C0C0" valign="top"><font face="Arial" size="3"><b>Dienstort</b></font></td>
<td width="99" height="25" align="left" bgcolor="#C0C0C0" valign="top"><font face="Arial" size="3"><b>Zimmer</b></font></td>
<td width="89" height="25" align="left" bgcolor="#C0C0C0" valign="top"><font face="Arial" size="3"><b>Tel.</b></font></td>
</tr>

<%
If Not rs.eof Then
do while Not rs.eof
%>

<tr>
<td width="163" height="25" align="left" valign="top"><font face="Arial"><%response.Write rs.Fields("Name")%></font></td>
<td width="123" height="25" align="left" valign="top"><font face="Arial"><%response.Write rs.Fields("Vorname")%></font></td>
<td width="212" height="25" align="left" valign="top"><font face="Arial"><p align="left"><%response.Write rs.Fields("Amt")%></font></td> <center>
<td width="91" height="25" align="left" valign="top"><font face="Arial"><%response.Write rs.Fields("Standort")%></font></td>
<td width="99" height="25" align="left" valign="top"><font face="Arial"><%response.Write rs.Fields("Zimmer")%></font></td>
<td width="89" height="25" align="left" valign="top"><font face="Arial"><%response.Write rs.Fields("Telefon")%></font></td>

<%
rs.MoveNext
loop

else

Response.Write "<p>Es wurde leider keine Übereinstimmung für den Suchbegriff - <font color=#FF0000>"&Request.QueryString("suche")&"</font> - gefunden!</p> "

End If

rs.Close
Set rs = Nothing
db.Close
Set db = Nothing
%>
</table>

----------------------------------------------------------------------------------------------------------
Hoffe auf Hilfe....

Danke
 
Hi

dass die Anwendung langsam ist, das wundert mich nicht. Du hast min. 2 dicke Dinger drin, die den Server ins Schwitzen bringen.

1. Abfrage mittels like-Operator.
Abfragen mit dem like-Operator sind eben serverlastig. Je mehr, desdo lastiger.
Ein Suchformular zu erstellen, ist immer eine kniffelige Sache. Man muss sich vorher überlegen, was macht Sinn und was nicht und ob jedes Feld überhaupt durchsucht werden muss.

z.B. Suche nach Vornamen

- Mögliche Lösungen wären, die SQL dyn. aufzubauen.
- Einige Abfragen im Vorfeld bereits ausschließen.
- Das Formularfeld z.B. abfragen, ob es einen num. Wert enthält oder einen alphanum. Enthält es einen num. dann nur die Felder durchsuchen lassen, die auch dafür in Frage kommen.
- Mal nachsehen, ob nicht einige Suchkriterien fest hinterlegt werden können z.B. in Comboboxen oder Checkboxen und das entspr. Feld mit = abfragen.
- Indizies setzen auf Felder, die am meisten besucht werden.
- macht es Sinn, alle Datensätze auszugeben oder nur eine bestimmte Anzahl (top x) und..und ..und

Es gibt noch mehr Möglichkeiten, einfach richtig durchdenken.

2. Die Ausgabe-Tabelle
Je mehr html-Code sich in einer Ausgabe befindet, desdo langsamer wird das ganze. Viele Formatierungen kann man in einer CSS-Datei festlegen und müssen nicht in der Tabelle mitgeführt werden z.b. bgcolor, Schriftgröße, Font-family. Ein Tabellenaufbau ist halt langsamer als ein Aufbau ohne Tabelle.

Versuch es spaßeshalber mal ohne Tabelle und ohne Formatierungen, nur mit einem <br> getrennt, dann wirst Du schon einen Unterschied feststellen.

Außerdem kann man zur Kontrolle mal einen Timer einsetzen.

Response.Write "Startzeit: " & Now() & "<br>"
timStart = Timer
' --- öffnen der Tabelle
' --- Ausgabe der Daten
timEnd = Timer
Response.Write "<br>Endzeit: " & Now() & "<br>"
Response.Write "<br>"
Response.Write "Verbrauchte Zeit in Sekunden: " & _
timEnd - timStart & "<br>"
 
Danke für die umfangreiche antwort.

leider prallen hier welten aufeinander - ich bin halt ASP-Beginner....

Ich habe versucht die "like" abfragen in "=" umzuwandeln aber das will irgendwie nicht.

Habt ihr vielleicht noch nen Tip

Danke im Vorraus
 
Hallo painkiller,

Luzie hat mit Ihren Angaben recht, aber so ganz erklärt es die 5-10 Sekunden nicht. Um was für ein System handelt es sich denn? Windows NT4 oder Win9x/me? Wenn ja, setze einmal die nachfolgenden Zeilen als erste Zeilen in die Seite ein:
<% @ Language="VBScript" %>
<% Response.Buffer = true %>

Eventuell löst dies Dein Problem.
 
Hehhh der Tip war Gold wert. Die Zeiten haben sich halbiert....

Es ist ein Winn2000 SP3 Server auf dem der IIS 5 läuft.

Die Datenbank ist Access97.


Die Firma dankt!
 
Hallo painkiller,

>Hehhh der Tip war Gold wert. Die Zeiten haben sich halbiert....
>Es ist ein Winn2000 SP3 Server auf dem der IIS 5 läuft.
>Die Datenbank ist Access97.
Windows 2000? Dann wurde wohl im IIS die Pufferung deaktiviert. Was bewirkt Response.Buffer? Die Seite wird an den Client erst dann gesandt, wenn die Seite vollständig abgearbeitet wurde, oder ein Response.Flush oder Response.End gesetzt wurde. Diese Zwischenspeicherung/Pufferung wurde seit Windows 2000 standardmässig aktiviert, zu Recht. Was ist der Vorteil in der Pufferung? Beispiel Deine Schleife: Jede Ausgabe wird dann gleich an den Client gesandt, dadurch entsteht wesentlich mehr Netzwerktraffic und mehr Belastung für den Server. Deshalb die Pufferung standardmässig aktivieren, kann zwar etwas mehr an Belastung für den Speicher bedeuten, die meisten Server haben jedoch mehr als genügend Speicher und der Vorteil durch die Pufferung ist einfach zu gross.

Diese Pufferung kann man im ISM de-/aktivieren. ISM = Internet Service Manager, Programm um Einstellungen des IIS vorzunehmen. Was mir noch auffiel: Es wird Access 97 unter Win2000 eingesetzt, das kann leider hier und da Probleme geben. Es wird dann z.B. Fehler 80004005 Unbekannter Fehler gemeldet. Leider gibt es hierfür keine echte Lösung, hier hilft nur ein Update auf Access 2000. Falls die Seite viel abgerufen wird, würde ich überlegen, das ganze auf MS SQL-Server oder MySQL zu portieren.

>'Datenbank öffnen
>strConnection = "Driver={Microsoft Access Driver (*.mdb)};DBQ="
>strConnection = strConnection & Server.MapPath("mdb/db2_2000.mdb")
>strConnection = strConnection & ";DriverId=25;FIL=MS Access;MaxBufferSize=4096;PageTimeout=10;"
Das würde ich in einen OLEDB-Treiber ändern, spart nochmals 5-10%

><<title>Telefonbuch</title>
Ein < zuviel!

Gib mal als Suchbegriff ein Prozentzeichen ( % ) ein. Wahrscheinlich werden alle Einträge angezeigt, dann noch ein Hochkomma ( ' ), Fehlermeldung? Eine öffnende Eckige Klammern ( [ ), Fehlermeldung? SQLEncode: http://www.asphelper.de/Tip/Tip50.asp

Ein </tr> fehlt in der Schleife noch.

>Die Firma dankt!
Gern geschehen! Wünsche noch einen schönen Tag!
 
Back Again...


Also, bei % kommen alle Datensätze.

>Mit Hochkomma erhalte ich folgende Fehlermeldung.
>
>HTTP 500.100 - Interner Serverfehler - ASP-Fehler
>Internet-Informationsdienste
>
>--------------------------------------------------------------------------------
>
>Technische Informationen (für den Support)

>Fehlertyp:
>Microsoft OLE DB Provider for ODBC Drivers (0x80040E14)
>[Microsoft][ODBC Microsoft Access Driver] Syntaxfehler in >Abfrageausdruck 'Telefonliste.Name like ''%'or Telefonliste.Telefon like ''%'or >Amt.Amt like ''%'or Telefonliste.Zimmer like ''%'or Telefonliste.standort like ''%'or >Amt.Amtsnummer like ''%''.
>/public/neu/landratsamt_verwaltung/telefon/telefon_lotus.asp, line 24
>
>
>Browsertyp:
>Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QXW0339t)
>
>Seite:
>GET /public/neu/landratsamt_verwaltung/telefon/telefon_lotus.asp
>
>Zeit:
>Dienstag, 17. Februar 2004, 12:00:37
>
>
>Weitere Informationen:
>Microsoft Support


Mit der [ erhalte ich folgenden Fehlercode

>HTTP 500.100 - Interner Serverfehler - ASP-Fehler
>Internet-Informationsdienste
>
>--------------------------------------------------------------------------------
>
>Technische Informationen (für den Support)
>
>Fehlertyp:
>Microsoft OLE DB Provider for ODBC Drivers (0x80040E07)
>[Microsoft][ODBC Microsoft Access Driver] Zeichenfolgenmuster unzulässig
>/public/neu/landratsamt_verwaltung/telefon/telefon_lotus.asp, line 24
>
>
>Browsertyp:
>Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QXW0339t)
>
>Seite:
>GET /public/neu/landratsamt_verwaltung/telefon/telefon_lotus.asp
>
>Zeit:
>Dienstag, 17. Februar 2004, 12:03:29
>
>
>Weitere Informationen:
>Microsoft Support


Interresant wäre noch Luzies Tip einige "like" durch "=" zu ersetzen.
Das geht aber irgendwie nicht ohne Weiteres. oder doch?

Danke nochmal für die Mühen aber ich bin leider Gottes ROOKIE...

PS: Ich war gerade auf deiner Website - jetzt hab ich Kopfweh...
 
Zuletzt bearbeitet:
Hi

like durch = ersetzen, geht nicht so einfach.
Like mit wildcards (%) liefert Dir eine bestimmte Zeichenfolge, die vorkommen kann. = liefert Dir nur nur dass, was auch aufgrund der Abfrage im Feld steht. Ist der Suchbegiff Meier, wird auch nur Meier angezeigt und nicht Meierlein.

Bei solchen Suchformularen ist es wichtig, richtige Schritte zu überdenken. Vor allem auch die Userfreundlichkeit zu berücksichtigen. Mit = meinte ich, im Vorfeld schon mal eindeutige Felder wie z.b. Abteilungen, Regionen etc. über eine Combobox auszugeben. Evtl. mit Checkbox auswählen lassen, ob nach Telefon-Nr. oder Name gesucht wird. Hier kann man dann aufgrund der Rückmeldungen aus den Formularfeldern die SQL aufbauen.

Was ich auch noch sehr wichtig finde, bring Deinen html-Code in Ordnung, löse Formatierung über CSS. Dies benötigt auch Ladezeit.
 
Das wars na klar geht = mit Wildcards nicht. grober Denkfehler meinerseits. Hab jetzt unötige Wildcards rausgehauen, und ein paar "like" durch "=" ersetzt.

Wird immer schneller.

Werd mich dann mal an den Quellcode machen.

Aber jetzt sind die Abfragezeiten schon mal erträglich geworden.

0,8s bis 5s je nach Menge der Abgefragten Werte.

Vielen Dank nochmal.

Daniel
 
Hallo painkiller,

>PS: Ich war gerade auf deiner Website - jetzt hab ich Kopfweh...
:) Ich hoffe, die Kopfschmerzen sind inzwischen wieder verflogen.

ich möchte jetzt nicht noch mehr für Kopfschmerzen sorgen, aber etwas habe ich noch. Kann der Besucher eigentlich mehrere Werte angeben? Soll dann nach jedem Begriff gesucht werden, oder als ganzer Begriff? Als nächstes: Was passiert, wenn z.B. 100 Einträge ermittelt wurden, werden dann alle angezeigt? Eventuell wäre ein Paging hilfreich.

>0,8s bis 5s je nach Menge der Abgefragten Werte.
Meiner Ansicht nach kann man da aber noch mehr unternehmen. Die Tipps von Luzie solltest Du auf jeden Fall wahrnehmen! Als nächstes sollte man dann noch prüfen, ob es eine Telefonnummer ist, eine Zimmernummer, eine Amtsnummer oder Standort ist, wenn nein, nicht danach suchen.

Es gibt noch weitere Tricks, aber das wären wohl jetzt gerade zuviele Kopfschmerzen! ;-)

Wegen dem SQLEncode, habe das jetzt mal schnell geändert, sieht jetzt so aus:
Code:
Dim strSuche, strOrderBy
strOrderBy = SQLEncode(Request.QueryString("b"))
strSuche = SQLEncode(Request.QueryString("suche"))

SQL = "SELECT Amt.Amt, Telefonliste.Name, Telefonliste.Vorname, " & _
    "Telefonliste.Standort, Telefonliste.Telefon, Telefonliste.Zimmer, " & _
    "Amt.Amtsnummer FROM Amt INNER JOIN Telefonliste ON " & _
    "Amt.AmtID = Telefonliste.AmtID WHERE " & _
    "Telefonliste.Name like '" & strSuche & "%' or " & _
    "Telefonliste.Vorname like '" & strSuche & "%' or " & _
    "Telefonliste.Telefon like '" & strSuche & "%' or " & _
    "Amt.Amt like '" & strSuche & "%' or " & _
    "Telefonliste.Zimmer like '" & strSuche & "%' or " & _
    "Telefonliste.standort like '" & strSuche & "%' or " & _
    "Amt.Amtsnummer like '" & strSuche & "%' ORDER by " & strOrderBy


Public Function SQLEncode(ByVal strText)
    'SQLEncode <-> Version 1.1, letzte Änderung am 2004-02-04
    If len(strText) = 0 OR strText = Null Then
        SQLEncode = ""
        Exit Function
    End If
    
    Dim i, KlammerAuf, KlammerZu
    
    KlammerAuf = InStr(1, strText, "[")
    KlammerZu = InStr(1, strText, "]")
    
    If KlammerAuf > 0 And KlammerZu > 0 Then
        i = 0
        Do While KlammerAuf > 0 Or KlammerZu > 0
            If (KlammerAuf < KlammerZu And KlammerAuf > 0) _
                    Or Not KlammerZu > 0 Then
                'KlammerAuf ersetzen
                strText = Left(strText, KlammerAuf - 1) & "[[]" & _
                            Right(strText, Len(strText) - KlammerAuf)
                i = KlammerAuf + 3
            Else
                'KlammerZu ersetzen
                strText = Left(strText, KlammerZu - 1) & "[]]" & _
                            Right(strText, Len(strText) - KlammerZu)
                i = KlammerZu + 3
            End If
            If i > Len(strText) Then
                Exit Do
            Else
                KlammerAuf = InStr(i, strText, "[")
                KlammerZu = InStr(i, strText, "]")
            End If
        Loop
    ElseIf KlammerAuf > 0 Then
        strText = Replace(strText, "[", "[[]")
    ElseIf KlammerZu > 0 Then
        strText = Replace(strText, "]", "[]]")
    End If
    strText = Replace(strText, "'", "''")
    strText = Replace(strText, "%", "[%]")
    strText = Replace(strText, "_", "[_]")
    
    SQLEncode = strText
End Function

Natürlich ungeprüft usw.
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück