02. marts 2005 - 11:52Der er
18 kommentarer og 2 løsninger
manglende connection close indfydelse på performance
Jeg har et site der har performance problemer ved høj belastning.
Jeg ved at jeg flere steder i min kode har glemt
objCon.close set objCon = nothing
Hvordan kan jeg teste om dette har væsentlig indflydelse på performance?
Kan jeg evt. under en mindre belastning overvåge systemet via MSSQL og et eller andet sted se om der er ulukkede connections der står og bruger serverplads ?
Vi bruger ADO, men ikke-lukkede connections giver ikke fejl (tror vi) men vi får dårlig performance.
Vi har logget forskelligt under den høje belastning og kan se at der har været nogen "internal Server Error"-fejl , men er det en sådan fejlbesked du forventer ved ikke lukkede connections ?
Connections skal lukkes, det er klart, så det må I i gang med.
Problemet findes to steder:
Serveren har brug for at kunne slippe connections hurtigt, ellers vil de eksistere indtil timeout. En rigtig god ting er i øvrigt at Dim'e objekterne:
Dim Con Set Con = ServerCreateObject("ADODB.Connection")
osv.
MSSQL har også brug for at lukke, især hvis du laver mange Update eller Inserts. Hvis du bruger denne syntaks:
Set Rec = Con.Execute("SELECT ....")
- så har du et problem. Du skal bruge: Dim Con, Com, Rec Set Con = ServerCreateObject("ADODB.Connection") Set Com = Server.CreateObject("ADODB.Command") Con.Open "ConnectionString her, ok?" Com.ActiveConnection = Con Set Rec = Server.CreateObject("ADODB.Recordset") Com.CommandText = "SELECT ...." Rec.Open Com, , 0, 1
'hvad du nu vil
Rec.Close Con.Close Set Con = Nothing Set Com = Nothing Set Rec = Nothing
Parametrene 0 og 1 er hhv CursorType og LockType.
Cursoren bestemmer om du har mulighed for at "bladre tilbage", og om du kan få et RecordCount. Skal du ikke kunne bladre tilbage med Rec.MovePrevious, og skal du ikke bruge et RecordCount, så skal du bruge 0.
Locktype bestemmer om data skal låses indtil du har sluppet dem igen, fordi du vil have lov til at ændre dem. Hvis du ikke skal ændre data, men bare læse dem, skal du bruge 1.
Hvis du vil have alle faciliteter kan du bruge
Rec.Open Com, , 3, 3
Så behøver du egentlig ikke flere som udgangspunkt.
En anden vigtig grund til performanceproblemer er mangel på indexer. Først og fremmest skal alle tabeller have en Primary Key, og alle felter der bruges som relaterede felter, eller Foreign Keys, skal indexeres
>>ldanielsen ved en select plejer jeg at gøre således (når jeg husker close)
dim strSQL, objRec, objCon strSQL = strSQL & "SELECT * from tabel" & vbcrlf Set objRec = Server.CreateObject("ADODB.Recordset") Set objCon = Server.CreateObject("ADODB.Connection") objCon.Open strCon objRec.Open strSQL, objCon, AdOpenStatic, AdLockReadOnly, AdCmdText
if not objRec.eof then 'noget end if
objRec.close Set objRec = nothing objCon.close Set objCon = nothing
ved en insert eller update plejer jeg at gøre således
dim objCon, strSQL strSQL = "INSERT eller update ..." Set objCon = Server.CreateObject("ADODB.Connection") objCon.Open strCon objcon.execute strSQL objCon.close set objCon = nothing
Ser du problemer i dette ?
Jeg er ikke sikker på jeg forstår hvad dit Com objekt gør, Men jeg vil meget gerne lære. Hvis mine flere hundrede inserts og updates skal laves om gør jeg det gerne hvis du kan overbevise mig om at det vil betyde en performance forbedring.
Vi har ladet databasen indexere og MSSQL sagde at det gav 17%, men det hjælper ligesom ikke nok når når svartiderne når op over 10 sekunder.
Det der er vigtigt er at du får sat de mindst resourcekrævende properties på dit Recordset, og det gør du. Det ser helt rigtigt ud.
Ang Command: En Command er det object der indeholder CommandText, dvs din sql, Parameters til brug ved stored procedures, og Commands kan være af forskellig type. Commands er knyttet til en connection med Command.ActiveConnection
Hvis du ikke opretter et Command objekt vil ADO selv lave det når du beder om at "Open" et recordset, eller "Execute" en sql-sætning. ADO vil udfra sammenhængen sætte de korrekte properties, men det er lidt ekstra arbejde for serveren.
Hvis du selv laver en Command kan du styre det præcist, og du vil næsten altid kunne nøjes med én Command på en side, som du så genbruger, i modsætning til de evt. mange der automatisk vil dannes. Endelig kan du sætte dem til Nothing, og således være helt sikker på at resourcerne frigives med det samme. Jeg vil tro at Commands ellers vil få lov til at timeout'e, men er faktisk ikke helt sikker på det.
Jeg ved heller ikke hvor mange resourcer man kan spare, men det er nok marginalt.
I har ladet databasen indexere, det lyder som om I bruger en databasedesigner udefra, eller er det noget software der gør det? Igen, er der Primary Keys på alle tabeller, og Foreign keys de rigtige steder? Det er meget vigtigt, jeg har selv oplevet at en query kører 10 til 20 gange så hurtigt efter at de rigtige indexer blev lavet.
Giv os evt. et eksempel på en proces der varer for længe, og lad os give et bud på hvorfor, og hvilke indexer der burde være.
Det var noget software vi brugte til at indexere databasen på baggrund af workload.
Jeg mener ikke jeg har en eneste tabel uden primary key. Foreign keys bruger jeg ikke da jeg synes det er for besværligt når man ind imellem ændre i databasen eller flytter databasen mellem servere.
Jeg vender tilbage senere når jeg har nogle logfiler der fortæller noget om hvilke sql-fejl og asp-fejl der har været undervejs.
Tror i at det har væsentlig indflydelse at jeg i mine select-sætninger bruger låsningstype AdLockReadOnly og ikke AdLockOptimistic ? Hvis AdLockReadOnly kan låse for andre brugeres inserts og updates i samme tabel er jeg nemlig ret sikker på at det vil have indflydelse på performance. Ved I om "select tabel with unlock where ..." har smme effekt som AdLockOptimistic ? (eller er jeg helt hen i skoven) ?
Jeg kan se at mine linier i indlæg "04/03-2005 09:01:51" er blevet cuttet noget af
I den første linie står længere ude
deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
Da jeg ikke erindre at have en eneste begin tran ... end trans i mit site og arne_v siger min AdLockReadOnly ikke låser noget forstår jeg ikke hvordan der kan opstå en deadlock ? -- noget må der da være låst ?
Det kan være jeg forstår begrebet transaktion forkert... Selvfølgelig laver jeg insert og updates , men jeg har ingen stored procedures og triggers. Jeg laver inserts og updates som i "03/03-2005 00:15:58". Men der angiver jeg ikke nogen parameter a la AdLock.... inserts og updates kan vel ikke låse noget i sig selv.
Jeg har dog noget der er lidt voldsommere, som f.eks en select efterfulgt af en lykke hvor jeg for hver forekomst indsætter i en anden tabel. Dette efterfølges så af en delete af de indgange jeg først selectede.
Jeg er blevet enig med mig selv om at mit sites dårlig performance når der var flere hundrede samtidige brugere på som lavede mange insterts,updates og deletes samtidig ved brug af de samme tabeller skyldes
1)Mine algoritmer er langt fra optimerede og jeg laver flere connections end strengt nødvendig pr bruger 2)Jeg glemmer rent faktisk en del steder at lukke mine connections efter endt brug. 3)Jeg fandt denne interessante artikel omkring MS-SQL servers ikke optimale brug af låsning: http://www.4guysfromrolla.com/webtech/101100-1.shtml, hvori der foreslås at man ved at bruge "with (nolock)" i select-sætninger og "with (rowlock)" i update og deletes kan forhindre at ms-sql-serveren låser mere end højst nødvendigt.
3) forklarer i hvert fald de 250 "was deadlocked on lock resources with anoher process and has been chosen as the deadlock victim. Rerun the transaction" fejl der blev logget De ca 4000 "ASP_0147|500_Server_Error" fejl (som ikke er scriptstimeout) kan jeg ikke rigtig greje og jeg er ikke kommet nærmere ved at søge på nettet.
Så jeg forsøger at forbedre 1)-3) til næste gang.
Hvis I lægger et svar hver får i noget for venlig deltagelse
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.