Zásady psaní ASP – optimalizace sessions a práce s databází

31. ledna 2001

Jedním z problémů při psaní webových aplikací je bezesporu to, že nikdy nevíte kolik lidí nakonec bude tuto aplikaci využívat. Může se stát že na vaše stránky přijde 5 lidí denně, ale může se také třeba stát, že po masivní reklamní kampani se na váš web přihrnou tisíce návštěvníků za hodinu a aplikace, která s tím nepočítala se zhroutí. Dnešní článek je o tom, jak vylepšit svoji práci se sessions a databázemi.

Tento článek mírně navazuje na článek o zásadách při psaní ASP, tentokrát se však netýká čistoty kódu a srozumitelnosti programu, ale spíše minimalizace výkonu, který vaše aplikace spotřebovává. Je třeba si totiž uvědomit, že (zatím) vaše aplikace asi nepoběží na serveru sama, ale společně s dalšími aplikacemi hostovanými na stejném serveru a využívajícími společně kapacitu připojení do Internetu. Proto je třeba dbát několika zásad – dalo by se říci „zásad slušného chování“ každé aplikace. Nejde samozřejmě jen o to, abyste neomezovali ostatní aplikace, ale hlavně o to, aby vaše aplikace/stránka byla co nejvíce dostupná. Nikoho jistě nepotěší, když jeho web není většinu dne přístupný, protože nestíhá vyřizovat požadavky na stránky.

Sessions

Sessions používejte jen tam, kde je potřebujete. Možná jste na českém Internetu slyšeli spoustu názorů na to, že sessions jsou špatná věc a že by se neměli používat vůbec, já si však myslím opak. Tedy ne, že by se měli používat neustále, ale že jejich použitím nic nezkazíte. Jednou z nevýhod sessions je, že samozřejmě zabírají na serveru určité množství systémových prostředků a proto je třeba zvážit, jestli je skutečně potřebujete nebo ne. Také je vhodné zvážit použití sessions v případě, že budujete web s plánovanou obrovskou návštěvností – pak by možný bylo vhodnější od sessions upustit a nahradit jejich funkci jinými prostředky. Každá session (sezení) totiž trvá ještě 20 minut potom, co si uživatel vyžádal ze serveru poslední stránku. Hodnota 20 minut je standardní nastavení, které jde samozřejmě změnit. Pokud zjistíte, že nepotřebujete udržovat stav session tak dlouho, tak tuto hodnotu zkraťte, případně sessions úplně vypněte.

K nastavení sessions pro vaši aplikaci se dostanete tak, že spustíte konzoli pro ovládání Internet Information Serveru, pravým tlačítkem klepnete na vaši aplikaci. Na kartě Directory (Adresář) je v dolní části tlačítko Configuration (Konfugurace). Stiskněte a vyberte prostřední záložku Možnosti aplikace. Tam můžete sessions úplně vypnout nebo nastavit kratší délku trvání.

Nastavení sessions ve Windows 2000

Pokud sessions potřebujete, ale máte několik stránek, které je nevyužívají, je dobré vypnout sessions jenom pro tyto stránky. Příkladem takového webu mohou být třeba firemní stránky, které používají sessions v sekci, do které je nutné se autorizovat napsáním hesla. Je ale zbytečné, aby se session zakládala při prohlížení obyčejných stránek o společnosti a zabírala místo v paměti. Session můžeme pro jednotlivou stránku vypnout pomocí následující direktivy:

<%@ EnableSessionState=False %>

Tato direktiva MUSÍ být na stránce jako první (na prvním řádku). Direktiva může být na stránce jenom jedna, pokud tedy potřebujete sdělit skriptovému stroji direktiv více, musíte je spojit do jedné. Např. pro specifikaci standardního jazyka a vypnutí sessions dáme na stránku:

<%@ Language=VBScript EnableSessionState=False %>

Práce s databázemi

Práce s databázemi je jednou z nejnáročnějších operací, jakou můžete na stránkách provádět. Z tohoto důvodu je nesmírně důležité správně si aplikaci navrhnout a pracovat s databázemi jenom v nutných případech. Pro práci s databázemi platí ve stručnosti tyto zásady:

Spojení s databází udržujeme jenom nezbytně nutnou dobu a potom ho ihned zavíráme. To samé platí pro recordsety (skupiny záznamů). Vytvoříme spojení na databázi, otevřeme požadovaný recordset, získáme data, zavřeme recordset a spojení. Tak by měla ve stručnosti probíhat práce s databází. Samozřejmě protože samotné navázání spojení na databázi trvá velmi dlouho, nebudeme ho na stránkách neustále zavírat a otevírat při každém použití recordsetu, ale necháme trvat jedno spojení v průběhu celé práce – ale ukončíme ho okamžitě, jakmile ho nebudeme potřebovat. Uvědomte si, že i když jde o zlomky milisekund, pokud přijde na vaši stránku hodně návštěvníků, tyto zlomky se pěkně (nebo spíš nepěkně) nasčítají a někdo pak může čekat na odezvu webového serveru velmi dlouho a někdy se ani nemusí dočkat.

Správně:
<%
Response.Write "Tady si provadime nejaky kod, treba jako vypisovani hlavice apod."
strDbCnn = "zde bude connection string na databazi"
‚ vytvorime obejkty connection a recordset
Set cnnDatabaze = Server.CreateObject("ADODB.Connection")
Set rstZaznam = Server.CreateObject("ADODB.RecordSet")
‚ nadefinujeme si SQL dotaz a otevreme databazi a recordset
strSQL = "SELECT jmeno, prijmeni FROM cloveci WHERE plat>5000"
cnnDatabaze.Open strDbCnn
rstZaznam.Open strSQL, cnnDatabaze
Do Until rstZaznam.EOF
   strJmeno = CStr( rstZaznam("jmeno") )
   strPrijmeni = CStr( rstZaznam("prijmeni") )
   Response.Write strJmeno & " " & strPrijmeni & "<br>"
   rstZaznam.MoveNext
Loop
‚ okamzite poskonceni prace zavirame recordset i databazi
rstZaznam.Close
cnnDatabaze.Close
rstZaznam = Nothing
cnnDatabaze = Nothing
%>
Špatný příklad:
<%
‚ vytvorime obejkty connection a recordset
Set cnnDatabaze = Server.CreateObject("ADODB.Connection")
Set rstZaznam = Server.CreateObject("ADODB.RecordSet")
‚ tady provadime zbytecne kod, ktery jsme klidne mohli provest predtim
strDbCnn = "zde bude connection string na databazi"
Response.Write "Tady si provadime nejaky kod, treba jako vypisovani hlavice apod."
‚ otevreme databazi, a opet zbytecne definujeme nejake veci, ktere jsme mohli provest predtim
cnnDatabaze.Open strDbCnn
strSQL = "SELECT jmeno, prijmeni FROM cloveci WHERE plat>5000"
rstZaznam.Open strSQL, cnnDatabaze
‚ dalsi zbytecny kod, ktery mohl klidne probehnout PRED otevrenim databaze
Response.Write "bla bla bla…"
Do Until rstZaznam.EOF
  strJmeno = CStr( rstZaznam("jmeno") )
  strPrijmeni = CStr( rstZaznam("prijmeni") )
  Response.Write strJmeno & " " & strPrijmeni & "<br>"
  rstZaznam.MoveNext
Loop
‚ opet zbytecnosti, ktere mohou probehnout PO ZAVRENI databaze
Response.Write "ble ble ble…"
‚ zavreme databazi – sice pozde, ale mnohem lepsi nez ji nezavrit vubec
rstZaznam.Close
cnnDatabaze.Close
rstZaznam = Nothing
cnnDatabaze = Nothing
%>

Ve druhém špatném příkladu můžete vidět zbytečné kusy kódu, který klidně mohl proběhnout před nebo po uzavření spojení s databází aniž by to nějak ovlivnilo chování programu.

Při práci s databází, která to umožňuje, je také více než vhodné používat uložené procedury (stored precedures). Tedy netvořit dotazy v ASP a pak je předávat serveru, ale volat příslušnou uloženou proceduru, která vykoná příslušný dotaz. Uložené procedury jsou vhodné minimálně ze dvou důvodů. Oddělujete aplikační logiku od databázové logiky a pak není např. vážnější problém změnit u fungující aplikace databázový server. Druhým a pro nás pádnějším důvodem je úspora času a výkonu – pro uloženou proceduru obsahující váš dotaz si totiž SQL server může vytvořit spouštěcí plán a pak vykonává dotaz rychleji. O uložených procedurách si povíme někdy příště.

Ve zdrojových kódech ASP stránek je také často vidět vkládání dat do databáze pomocí metody recordsetu AddNew. Postup je v podstatě takový, že otevřete záznam s takovou podmínkou, aby byl vrácen prázdný (d2l8 se to tak, že se vloží podmínka, která nejde splnit, např. 1=2). Potom pomocí metody AddNew přidáte nový záznam, který naplníte a pomocí metody Update uložíte zpět do databáze. Tak je to ale špatně! Mnohem lepší je vložit data pomocí klasického SQL příkazu INSERT. Je to nejen rychlejší, ale i kratší na psaní, takže obvykle opravdu není důvod uchylovat se k něčemu jinému. Navíc při tomto způsobu vůbec nepotřebujeme zakládat objekt RecordSet.

Správně:
<%
strDbCnn = "zde bude connection string na databazi"
‚ vytvorime obejkt connection a otevreme databazi
Set cnnDatabaze = Server.CreateObject("ADODB.Connection")
cnnDatabaze.Open strDbCnn
‚ provedeme vlozeni dat
strSQL = "INSERT INTO cloveci (jmeno,prijmeni,cislo_bot) VALUES (‚Luděk‘, ‚Roleček‘, 9)"
cnnDatabaze.Execute strSQL
‚ zavreme databazi
cnnDatabaze.Close
Set cnnDatabaze = nothing
%>
Špatný příklad:
<%
strDbCnn = "zde bude connection string na databazi"
‚ vytvorime obejkty connection a recordset
Set cnnDatabaze = Server.CreateObject("ADODB.Connection")
Set rstZaznam = Server.CreateObject("ADODB.RecordSet")
‚ nadefinujeme si SQL dotaz a otevreme databazi a recordset
strSQL = "SELECT jmeno, prijmeni, cislo_bot FROM cloveci WHERE 1=2"
cnnDatabaze.Open strDbCnn
rstZaznam.Open strSQL, cnnDatabaze
‚ zalozime novy zaznam, naplnime a ulozime
rstZaznam.AddNew
rstZaznam("jmeno") = "Luděk"
rstZaznam("prijmeni") = "Roleček"
rstZaznam("cislo_bot") = 9
rstZaznam.Update
‚ uzavreme zaznam a databazi
rstZaznam.Close
cnnDatabaze.Close
Set rstZaznam = nothing
Set cnnDatabaze = nothing
%>

A nakonec dnes poslední optimalizační pravidlo: pokud načítáte data z databáze, berte jenom ty, které skutečně potřebujete. Pokud tedy nepotřebujete všechny sloupce tabulky, přesně v SELECTu určete jenom ty, se kterými budete pracovat. Koneckonců ono je lepší sloupce vypisovat i v případě, že použijete všechny sloupce z tabulky – je to rychlejší. Pokud použijete v SELECTu hvezdičku (*), bude muset server zbytečně vytvářet prostor i pro data, která v současnosti vůbec nepotřebujete. Takže ješte naposledy jeden příklad:

Správně:
‚ urcime sloupce, ktere budeme pouzivat – jmeno a prijmeni
strSQL = "SELECT jmeno, prijmeni FROM cloveci"
….
Response.Write rstZaznam("jmeno") & " " & rstZaznam("prijmeni")
Špatný příklad:
‚ vybrali jsme vsechny sloupce z tabulky, ale pak pouzivame jenom dva
strSQL = "SELECT * FROM cloveci"
….
Response.Write rstZaznam("jmeno") & " " & rstZaznam("prijmeni")

To je pro dnešek vše. Příště si povíme něco o testování výkonu webových aplikací.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *