Diplomitöö: ASP.NET veebirakenduse optimeermine meediaorganisatsiooni näitel: Difference between revisions
(460 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
Siin lehel kirjutan oma diplomitööd. Alustan 19.märtsil probleemi kirjeldusega. | Siin lehel kirjutan oma diplomitööd. Alustan 19.märtsil probleemi kirjeldusega. | ||
= | =Olemasoleva olukorra ja probleemi kirjeldus= | ||
Selle peatüki eesmärk on anda lühike ülevaade Eesti Rahvusringhäälingust ja selle portaalidest ning olemasolevast lahendusest. | |||
== | |||
Eesti | ==Eesti Rahvusringhääling== | ||
''Ilus organisatsiooni skeem''<br/> | |||
Eesti Rahvusringhäälingu moodustavad kaks tele- ja viis raadioprogrammi, millele lisanduvad juurde veel mitmed uudiste- ja teemaportaalid. Organisatsioon hakkas sellisel kujul tegutsema 1. juunil 2007, kui ühendati Eesti Raadio ja Eesti Televisioon. Viimast esindavad ETV ja ETV2 ning raadiod Vikerraadio, Klassikaraadio, Raadio 2, Raadio 4 ja Raadio Tallinn. | |||
Rahvusringhäälingu kõige olulisem tegevus on sisu tootmine. | |||
Missiooniks on arendada ja hoida Eestit ning selleks kaasatakse inimesi Eesti riigi ellu, innustatakse vaba arutelu, edendatakse loomingulisust ja tegusust. Luuakse teabevõrgustik kõigi Eestiga seotud inimeste vahel kogu maailmas, oma programmides avardatakse Eesti inimeste maailmapilti, haritakse avalikus mõtteruumis osalejaid, väärustatakse inimeste isiklikku elu ja perekonda, kaitstakse eetilisi põhiväärtusi. | |||
Raadio-ja teleprogrammide kõrval mängivad olulist rolli missiooni täitmisel ka Eesti Rahvusringhäälingu internetiportaalid. Näiteks on antud organisatsioon loonud ainsana inglise keelse portaali, mis kajastab Eestit. Samuti tehakse seda ka vene keeles. TNS-i Emor andmetel oli Rahvusringhäälingu portaalide lugejaskond 2010. aasta lõpul enam kui 165 tuhat lugejat nädalas. Eesmärk on olla viie esimese ajakirjanduslikku sisu pakkuva portaali seas. | |||
Samuti on loodud võimalused jälgimaks kõiki tele- ja raadioprogramme otsesaateid üle maailma läbi interneti, et olla Eestis toimuvaga kursis. Praegu tegeletakse sellega, et tuua otsetoodang ka mobiili ja inimesed saaksid programme jälgida sõltumata seadmetest. Internetis saavad oluliseks ka ineteraktiivsed keskkonnad ja sotsiaalvõrgustikud. | |||
==Portaalide arendus ERR'is== | ==Portaalide arendus ERR'is== | ||
ERR'is tegeleb portaalide arendusega | ERR'is tegeleb portaalide arendusega portaalide arenduse üksus. Ametikult loodi see 1. jaanuar 2011. Praeguse hetkel kuuluvad meeskonda ametlikult 4 arendajat ja veebiarendusjuht. Eelnevalt vastutas arenduse eest üks isik. Kõik uued portaalid luuakse hetkel ASP.NET 4 platvormil, millega paralleelselt toimub vanema ASP.NET generatsiooni portaalide üle toomine uuemale versioonile. Lisaks .NET raamistikku kasutavatele portaalidele on hetkel veel ka PHP lahendusi, millele ei tehta enam väga suuri juurdearendusi. | ||
=== | |||
===PHP tehnoloogial portaalid Eesti Rahvusringhäälingus=== | |||
Alljärgnevas peatükis tutvustatakse erinevaid PHP portaale Eesti Rahvusringhäälingus. | |||
====PHP4 tehnoloogial arendatud portaalid==== | |||
PHP 4 portaalidest on kõige pikema ajalooga etv, mis loodi PHP4 tehnoloogial aastal 2003. Eksisteeris ka varem, kuid selle ajalugu on hetkel teadmata. Sellele järgnes uudisteportaal 2006ndal aastal, mis esialgu kandis nimetust etv24. Ilm loodi aastal 2009. | |||
<ul><li>etv.err.ee - ETV kanali portaal, võimalik jälgida tagantjärele saateid ja nende uudiseid.</li> | |||
<li>uudised.err.ee - uudiste portaal.</li> | |||
<li>ilm.err.ee - ilma portaal.</li> | |||
<li>meieoma.ee - lastele mõeldud portaal.<li></ul> | |||
====PHP5 tehnoloogial arendatud portaalid==== | |||
PHP5 portaalidest on kõige pikema ajalooga raadioportaalid. Alates 1995ndast aastast kuni aastani 2000 toimus nende haldamine kasutades staatilist HTML'i. Peale seda võeti kasutusele PHP3 ja aastal 2002 PHP4. 2007ndal aastal valmisid kõik raadioveebid baseerudes PHP5'le, neist viimane portaal - klassikaraadio, valmis sama aasta detsembris. | |||
Kõige uuemad lahendused on pood.err.ee ja teadus, mis valmisid 2010. aasta septembris. | |||
<ul> | |||
<li>pood.err.ee - võimalik osta ERR toodangut.</li> | |||
<li>Raadioportaalides on võimalik lugeda nendega seonduvaid uudisedeid, kuulata saateid arhiivist ja ka otse.</li> | |||
<ul><li>vikerraadio.err.ee</li> | |||
<li>r2.err.ee</li> | |||
<li>r4.err.ee</li> | |||
<li>raadiotallinn.err.ee</li> | |||
<li>klassikaraadio.err.ee</li></ul> | |||
<li>teadus.err.ee - teadus- ja haridussaadete portaal.</li> | |||
<li>raadioteater.err.ee - võimaldab kuulata vikerraadios esitatud kuuldemänge ja järjejutte.</li></ul> | |||
===ASP.NET platvormil portaalide arendus Eesti Rahvusringhäälingus=== | |||
''Miks? Kes?Kus? Kuidas?''<br /> | |||
2009 aastal lisandus ERR portaalidesse Arendusjuht. Tema ülesandeks oli analüüsida tehnoloogiate ja rakenduste hetkeseisu ning võimalikke lahendusi. Peale esimest poolaastat analüüse langetati otsus kasutada ühtset valmis võimekat veebimootorit ning osta sisse esmane arendus, kuna organisatsioonis puudus vajalik tööjõud. Selle tegevuse tulemusena alustati taotlust Riigihankele läbi Euroopa Struktuurifondide. Tehnoloogiliseks alusstandardiks sai Microsft.NET platvorm tänu vahendite võimekusele ja tööjõudlusele. Kuna hanked on pikk protsess siis alustati esimeste portaalide üleviimist ning uute rakenduste loomist. Kõige esimeseks rakenduseks sai keskportaal (err.ee) ning see hostiti Microlingi avalikus hostingus kuna .net platvormi infrastruktruu on üks osa riigihankest. Alates aastast 2010 omab organisatsioon minimaalset infrastruktuuri .net platvormi teenindamiseks siseselt ning aastal 2011 tarniti riigihanke raames hangitud riist ja tarkvarile platvorm mille lõplik avalik käivitamine toimub kevadel 2012. | |||
=== | ====ASP.NET 2.0==== | ||
ASP.NET 2.0 | <ul><li> | ||
err.ee -Eesti Rahvusringhäälingu keskportaal. | err.ee -Eesti Rahvusringhäälingu keskportaal.</li> | ||
om.err.ee - Taliolümpiamänge kajastav portaal. | <li>om.err.ee - Taliolümpiamänge kajastav portaal.</li></ul> | ||
====ASP.NET 4.0==== | |||
news.err.ee - Eestit kajastav ingliskeelne uudiste portaal | <ul><li>news.err.ee - Eestit kajastav ingliskeelne uudiste portaal</li> | ||
eestilaul.err.ee - Eesti Laulu ja Eurovisiooni kajastav teemaportaaal | <li>eestilaul.err.ee - Eesti Laulu ja Eurovisiooni kajastav teemaportaaal</li> | ||
otse.err.ee - Portaal, mis võimaldab jälgida ERR'i tele-ja raadiotoodangut reaalajas. | <li>otse.err.ee - Portaal, mis võimaldab jälgida ERR'i tele-ja raadiotoodangut reaalajas.</li> | ||
valijakompass.err.ee - teemaportaal mis aitas võrrelda inimestel enda seisukohti erakondade omadega. | <li>valijakompass.err.ee - teemaportaal mis aitas võrrelda inimestel enda seisukohti erakondade omadega.</li> | ||
koolifilm.err.ee - koolifilmi konkurssi läbiviimiseks loodud portaal | <li>koolifilm.err.ee - koolifilmi konkurssi läbiviimiseks loodud portaal</li> | ||
rus.err.ee - Eestit kajastav venekeelne uudisteportaal. | <li>rus.err.ee - Eestit kajastav venekeelne uudisteportaal.</li> | ||
retseptid.err.ee - portaal, kuhu lisatakse eetris olnud retsepte. | <li>retseptid.err.ee - portaal, kuhu lisatakse eetris olnud retsepte.</li> | ||
kodanik.err.ee - | <li>kodanik.err.ee - </li> | ||
jalgpall.err.ee - Portaal, mis kajastas jalgpalli MM 2010't | <li>jalgpall.err.ee - Portaal, mis kajastas jalgpalli MM 2010't</li> | ||
ring.err.ee - ERR portaalide registreeritud kasutajate.. | <li>ring.err.ee - ERR portaalide registreeritud kasutajate..</li> | ||
etv2.err.ee - kajastab ETV2'ga seotud uudiseid/üritusi. | <li>etv2.err.ee - kajastab ETV2'ga seotud uudiseid/üritusi.</li> | ||
</ul> | |||
==Probleemi kirjeldus== | |||
Teise põlvkonna ASP.NET portaalide jaoks loodud lahendus valmis kiirustades, kuna selle valmistamine toimus äärmiselt piiratud ajaraamis ja tööjõudu selle projekti tarvis oli vähe. Seetõttu puudus oodatava süsteemi põhjalik eelanalüüs. Rakenduse loomiseks kasutati töövõtteid, mis kiirendasid küll selle valmimise kiirust, kuid paratamatult kannatas selle all rakenduse kvaliteet (sh jõudlus). Ametlikku kasutuselevõttu eel ei olnud võimalik, tulevenalt ajaraamist, teha süsteemile täielikke jõudlusteste, mis näidanuks selle toimimist suurte koormuste korral. Teise põlvkonna ASP.NET portaalide mootori valmimise hetkel hakati seda lahendust kasutama vaid ühe portaali piires. Hiljem lisandus sellele platvormile täiendavaid portaale ning jõudluse küsimus muutus seepärast aktuaalseks. | |||
Arendusmeeskonda on lisandunud noori programeerijaid, kes ei ole piisavalt teadlikud kuidas tagada korraliku koodikvaliteeti. ASP.NET lahendusi on küll võimalik pealtnäha kiiresti ja kergelt luusa, kuid kasutades valesid tehnoloogiaid ning töövõtteid ja jättes optimaalse ressursikasutuse jälgimise tagataustale, mõjub see rakenduse jõudlusele negatiivselt. | |||
Poole aasta jooksul on lisandunud uusi .NET portaale, milledest enamus kasutab eelpool mainitud lahendust. Viimasel ajal on esinenud suurte koormuste korral märgatavaid jõudlusprobleeme. Üheks põhjuseks on kindlasti asjaolu, et kõiki .NET portaalide haldamiseks on kasutada ainult üks server. Ehk kui üks portaal hakkab kasutama väga palju ressurssi, siis mõjutab see ka teiste veebirakenduste tööd. See on kindlasti hetkel ka üheks turvanõrkuseks - leides ühel leheküljel ressursinõudliku protseduuri, saab seda kasutada kõikide Eesti Rahvusringhäälingu ASP.NET portaalide töö häirimiseks. Halvimal juhul lõpeb see serveri töö seiskumisega. Serveripargi jõudluse parandamiseks on täiendavad investeeringud riistvarasse hetkel välistatud. Kuna organisatsioon tegutseb internetimeedia turul ja laieneb sellel pidevalt, siis häired veebirakenduste töös mõjuvad mainele negatiivselt ning on oht kaotada külastajaid. | |||
Lähiajal on lisandumas antud serverile veel kaks täiesti uut portaali. Lisaks peavad hakkama mõned esimese põlvkonna portaalid kasutama "uut mootorit", üheks neist on sport, millele on oodata suurt külastajatearvu. Arvestades asjaolu, et juba praegu esineb jõudlusprobleeme, tuleb enne parandada olemasoleva lahenduse jõudlust. | |||
Antud peatükis andis autor ülevaate konkreetse organisatsiooni probleemi tekkimise põhjustest, lisaks käsitleb peatükis 2.3 "Optimeerimisest üldiselt" jõudlusprobleemide esinemist laiemalt. | |||
<br/> | |||
''See osa on selgelt liiga lühike'' | |||
''Võimalik viide, et probleemi aktuaalsust üldisena käsitleb autor peeatükis see ja see'' | |||
=Metoodika valik ja võimalikud lahendused= | =Metoodika valik ja võimalikud lahendused= | ||
Selles peatükis selgitab autor töös kasutatavat metoodikat ning annab ülevaate käsitletava teema valdkonnast üldiselt. | |||
==Metoodika== | ==Metoodika== | ||
Lahenduse leidmiseks kasutatakse olemasolevate materjalide analüüsi. Lõputöö käigus tutvutakse parimate praktikatega ja valitakse välja neist sobivaimad. Valiku tegemisel hinnatakse sobivust olemasoleva lahendusega. Kui valik on teostatud mõõdetakse praeguse lahenduse töökiirust. Peale seda võetakse kasutusele leitud optimeerimisvõimalused, mida rakendatakse kõigepealt testserveris, millele järgnevad uuesti mõõtmiseid. Võrreldakse saadud tulemusi ja tehakse järeldus. | Lahenduse leidmiseks teostab autor teoreetilise uuring kasutatakse olemasolevate materjalide analüüsi ning seejärel koostab olemasolevate rakenduste optimeerimise kava. Lõputöö käigus tutvutakse parimate praktikatega ja valitakse välja neist sobivaimad. Valiku tegemisel hinnatakse sobivust olemasoleva lahendusega. Kui valik on teostatud mõõdetakse praeguse lahenduse töökiirust. Peale seda võetakse kasutusele leitud optimeerimisvõimalused, mida rakendatakse kõigepealt testserveris, millele järgnevad uuesti mõõtmiseid. Võrreldakse saadud tulemusi ja tehakse järeldus. | ||
==ASP.NET veebirakenduse põhikomponendid ja töötsükkel== | |||
http://msdn.microsoft.com/en-us/library/ms178472.aspx <br /> | |||
Tänapäeval kasutab enamus veebirakendusi dünaamilist sisu kuvamist, kuna see teeb lehtede haldamise mugavamaks ja paindlikumaks. Enamasti hoitakse sisu andmetena andmebaasis, mida päritakse sealt, korrastatakse ja kuvatakse see järel kasutajatele. Selle kuvamise lihtsustamiseks on ASP.NET raamistikul mitmeid komponente nagu näiteks ''ListView'', ''GridView'' ja ka teisi listidel baseeruvad komponente. | |||
Nende kasutamiseks peab teadma kuidas töötab lehe elutsükkel ja kuidas toimub andmeseondamine ''(Data Binding)'' | |||
= | Komponendi andmeseondamise sündmus leiab aset pärast komponendi ''PreRender'' sündmust, mis leiab omakorda aset pärast lehe ''PreRender'' sündmust. See märgib protsessi algust, mile käigus hakatakse komponenti andmetega siduam. Seda meetodit saab kasutada manuaalseks andmebaasiühenduse avamiseks. | ||
== | |||
''RowCreated''(GridView) või ''ItemCreated'' sündmus (teisteö listidel baseeruvat komponentide puhul) täidetakse pärast andmesidumist. Seda saab kasutada manipuleerimiaks sisuga , mida kuvatakse. | |||
''RowDataBound''(GridView) või ''ItemDataBound(teistel listidel baseeruvate komponentide puhul) sündmuse käigus on rea või kirje puhul. Võimalik seda vormindada või kuvada sellega seotud andmeid konkreetse rea või kirjega. | |||
''DataBound'' sündmus kutsutakse andmetesidumise lõppedes.....34h ilma magamata... | |||
<table border="1"> | |||
<tr> | |||
<th>Etapp</th> | |||
<th>Kirjeldus </th> | |||
</tr> | |||
<tr> | |||
<td> | |||
<p>Lehe pärimine ''(Page request)''</p> | |||
</td> | |||
<td> | |||
<p>Leiab aset pärast lehe töötsükli algust. Kui seda päritakse, siis ASP.Net teeb kindlaks, kas lehte on vaja parsida ja kompileerida või on puhvris antud lehe versioon juba olemas. Viimase variandi puhul saab selle resveerida ilma töötsüklit jätkamata.</p> | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<p>Algus''(Start)''</p> | |||
</td> | |||
<td> | |||
<p>Algusfaasis väärtustatakse lehe atribuudid nagu näiteks ''Request'' ja ''Response''. Samuti otsustatakse, kas tegemist on tagasipostitusega või uue päringuga. Ükski komponent pole veel kättesaadav. </p> | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<p>Intsialieerimine''(Initialization)''</p> | |||
</td> | |||
<td> | |||
<p>Selle protsessi käigus loodakse komponendid ja lisatakse lehe komponentide kollektsiooni. Igale ühele neist luuakse unikaalne tunnus''UniqueID''. See on ainus töötsükli osa kus nägusid või pealhti saab dünaamiliselt muuta. ViewState pole veel taastatud. </p> | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<p>Laadimine''(Load)''</p> | |||
</td> | |||
<td> | |||
<p>Kui antud protsessi käigus ilmneb, et tegemist on tagasipostitamise, siis laetakse komponentide atribuudid ''view state' ja ''control state'''ist. Selles osas tuleb enamasti küsida andmebaasist andmeid.</p> | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<p>Tagasipostituse sündmuse töötlemine''(Postback event handling)''</p> | |||
</td> | |||
<td> | |||
<p>Kui tegemist on tagasipostitusega, siis kutsutakse välja kontrollide sündmusetöötlejad ''(event handler)''. Peale seda kutsutakse välja ''Valid'' meetod mis paneb paika ''IsValid'' atribuudi kõikidel kontrollidel ja lehele </p> | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<p>Renderdamine''(Rendering)''</p> | |||
</td> | |||
<td> | |||
<p>Siin toimub toimub viewstate'i salvestamine lehe ja kõikide komponentide jaoks. Selle protsessi käigus kutsub leht iga kontrolli jaoks välja ''Render'' meetodi, mis kirjutab lehe ja iga komponendi HTML'i ja saadab selle väljundisse.</p> | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
<p>Unload</p> | |||
</td> | |||
<td> | |||
<p>Meetod kutsutakse esile, kui leht on täielikult renderdatud ja kliendile saadetud. Sel juhu vabanetakse atribuutidest nagu näiteks ''Response'' ja ''Request'' ning toimub koristus.</p> | |||
</td> | |||
</tr> | |||
</table> | |||
==Optimeerimisest üldiselt== | |||
Tänapäeval on jõudlusprobleemid väga aktuaalsed, kuna IT-lahendused ning nende funktsionaalsute maht kasvab ajas kiiresti ning populaarsete veebirakenduste kasutajate hulk võib ajas eksponentaalselt kasvada. Kui veebirakendused on optimeerimata, siis võib kasutajate hulga lisandumine põhjustada halvimal juhul rakenduse töö katkemise või mitteootuspärase kasutajakogemuse. | |||
Tihti häirivad optimeerimata veebirakenduste tööd jõudlusprobleemid. Viimased kerkivad esile, kui süsteemile kasvab koormus ning tihti on nende tekkimist raske prognoosida. Olukorra iseloomustamiseks võib näite tuua liikluses: kell 4 öösel tööle sõit võtab alati vähem aega, kui seda teha hommikusel tipptunnil, teisalt võib juhtuda, et hommikul kell seitse toimub mõni oluline tähtsündmus ning öösel kell 4 on ootamatult tekkinud ummikud, kuna valgusfoorid ei tööta, aga liikluskoormus on suur. Nii võib juhtuda, et veebirakeendusel, kus tavapäraselt on paartuhat külastajat päevas, kasvab ühel päeval kasutajate hulk kümnetes kordades, kuna rakendusele tegi reklaami mõni meeldiakanal või populaarne sotsiaalmeedia kasutaja. | |||
Sellised näited on EERi kogemuses näiteks otse.err.ee portaalis, kus mõne aktuaalse sündmuse ajal võib kasvada kasutajate hulk järsult kümnetes kordades. Varasemalt on seda juhtunud eurovisiooni ja spordiülekannete puhul, mille tulemusena käitus leht mitteootuspäraselt. | |||
''Parem kirjuta vormis: selle vältimiseks saab kasutada...''<br /> | |||
Sellise olukorra vältimiseks on alati kõige lihtsam juurde soetada riistvara, mis annab omakorda juurde rohkem jõudlust. See on õigustatud ainult juhul, kui on kindlaks tehtud, et süsteem on juba optimeeritud ja olemasolevate vahenditega pole seda enam võimalik parandada. Vastasel juhul on tegemist probleemi ajutise peitmisega, mitte lahendamisega. Lisaks kulutatakse nii ebaotstarbekalt rahalisi vahendeid. Seega tuleks alati alustada probleemi lahendamist olemasoleva lahenduse analüüsiga ja võimaluse korral optimeerimisega. | |||
Süsteemi tuleb alati vaadata kui tervikut. Näiteks veebileht ei koosne ainult koodist, mis kirjutab välja vajalikke asju. Seda infot tuleb käia kuskilt pärimas - andmebaasist. Lehe reserveerimise eest vastutab aga server. Ükskõik millise eelpool mainitud osa halvasti töötamine mõjutab teisi. Parandades ühte osa, paraneb enamasti ka üldine jõudlus, kuid maksimaalse kasutegerui saavutamiseks tuleb vaadata rakenduse kõiki osasid. Edukalt probleemide lahendamisel võib nii vältida täiendava riistvara soetamist ja tagada parema süsteemi töökindluse. | |||
Enne optimeerimise alustamist tuleks veenduda, et plaanitav muudatus on vajalik ning see toob kaasa endaga jõudlusekasvu. Näiteks, kui kulutada kaks päeva andmebaasipäringu optimeerimiseks, mida tehakse kord aastas ja sellega võidetakse paar millisekundit, siis tegelikkuses on kaotatud 2 väärtuslikku tundi. Lisaks tasub jälgida, milliseid muudatusi toob tehtva muudatus kaasa olemasolevas lahenduses, kuna muutus, mis muudab koodi loetamatuks ja selle silumise raskeks ei pruugi olla alati õigustatud. | |||
Antud lõputöö raames vaatleeb autor eelkõige enimkasutatavaid ja suuremat jõudlusvõitu tagavaid võtteid ASP.NET veebirakenduse optimeerimiseks ning seda, kuidas neid olemasolevates ja ka uutes ERRi portaalimootorites rakendada. Tuuakse välja ka võimalused, kuidas mõõta erinevate rakenduse osade töötamiskiirust, millele tuleks selle juures tähelepanu pöörata ja milliseid muudatusi see endaga kaasa toob. Lisaks luuakse dokument, mida saab kasutada uute loodavate lahenduste varajaseks optimeerimiseks tulevikuks. Eeludseks on, et tegemist on .NET 4 raamistikuga ja andmebaasina kasutatakse SQL Server 2008 väljaannet, kuna need on antud töö aluseks. | |||
=Andmebaasi optimeerimine= | =Andmebaasi optimeerimine= | ||
''Siia pigem jutt, miks on andmebaaside optimeerimine rakenduse optimeerimise seisukohast oluline'' <br /> | |||
Mõiste "Andmebaas" defineerib wikipedia järgnevalt:"Andmebaas on korrastatud infokogum." http://et.wikipedia.org/wiki/Andmebaas Sellest vajaliku osa näitamise eest lõppkasutajale vastutab enamasti rakendus, mis pärib seda andmebaasist. Järelikult võib väita, et sellise rakenduse töö sõltub lisaks muule ka andmebaasist. See tõttu on viimase kiire ja optimaalne töötamine prioriteetne, kuna aeglane andmete leidmine ei mõjuta ainult andmebaasi enda tööd, vaid ka rakendust. Kui andmebaasi päringute täitmine võtab palju aega, peab rakendus ootama vajalike andmete järel, enne kui saab oma tööd jätkata. | |||
Antud peatüki eesmärgiks on kirjeldada võimalusi andmebaasi optimaalse töö tagamiseks. Lisaks peab autor vajalikuks kirjutada ka selle loomisest, kuna materjalide analüüsist selgus, et andmebaasi jõudluse tagamisel mängib väga suurt rolli ka selle disain. Halva arhitektuuriga andmebaaasi on väga keeruline optimeerida. | |||
==Microsoft SQL Server 2008 andmebaasimootori väljaanded ja nende funktsionaalsuste erinevus== | |||
Microsoft SQL Server 2008 on 6 erinevat väljaannet: Express, Workgroup, Web. Standard, Enterprise ja Datacenter. Antud nimekirja järjestus baseerub litsentside hinnal, milles kõige esimene on Express versioon. See on tasuta ja kõige väiksema funktsionaalsuse ning võimalustega. Töö käigus kasutas diplomitöö autor Standard väljaannet. Selle peatüki eesmärgiks on lühidalt võrrelda ja kirjeldada erinevate väljaannete funktsionaalsust lähtuvalt jõudlusest. | |||
'''Tabelite ja indeksite partitsioneerimine''' (''Table and index partitioning'') - võimaldab tabelid ja indeksid jagada väiksemateks osadeks. See on kasulik suure hulga andmete puhul, sest sellest väiksema osa läbi vaatamine võtab vähem aega ja ressurssi. SQL Server 2008 Bible 1428 <br/> | |||
'''Indekseeritud vaated '''''(Indexed views)'' - Tavalised vaated on virtuaalsed tabelid, mis luuakse alati iga päringu ajal uuesti. Indekseeritud vaadete puhul aga hoitakse selle päringu tulemusi andmebaasis tabelina. Lisaks sellel suudab päringuoptimeerija''(query optimizer)'' vajadusel loodud vaadet kasutada päringute täitmiseks ilma, et seda peaks ''FROM'' klauslis eraldi kirjeldama. <br /> http://msdn.microsoft.com/en-us/library/ms187864.aspx | |||
'''Andmete tihendamine'''''(Data Compression)''- võimaldab tihendada tervet kuhja''(heap)'', klasterdatud indeksit, klasterdamata indeksit, indekseeritud vaadet ja üksikut tabelit või indeksi partitsiooni. Näiteks mahub seetõttu lehtedele rohkem ridu ja kirjete läbi vaatamine toimub kiiremini. Peab arvestama, et kõik andmed ei kompresseeru hästi ja lisaks mõjutab see protsessori jõudlust. (SQL Server 2008 Bibile lk 1416) | |||
'''Ressursi haldur''' (''Resource governor'') - tööriist, mille abil saab määrata erinevatele päringutele ressursipiirangud ja limiidid. Kasulik olukorras, kus suur ja väikeseprioriteediga päring, kasutab palju ressurssi. Viimasele saab määrata maksimaalse protsessori kasutuse piiri. Nii võtab selle päringu täitmine küll rohkem aega, kuid kasutab vähem ressurse. http://msdn.microsoft.com/en-us/library/bb895232.aspx<br/> | |||
'''Parallel index operations''' - vähendab aega, mis kulub indeksite loomiseks ja ülesehitamiseks kasutades mitme protsessori tuge. http://msdn.microsoft.com/en-us/library/ms191292.aspx <br/> | |||
'''Parallel consistency checks (DBCC)''' - võimaldab andmebaasi käsurea päringuid täita paralleelselt ja seega kiiremini. <br/> | |||
'''Enhanced read-ahead scan ''' - ei saa aru. http://msdn.microsoft.com/en-us/library/ms191475.aspx <br/> | |||
<table border="1" style="text-align:center;"> | |||
<tr><th>- </th> <th>Express</th><th>Workgroup</th><th>Web</th> <th>Standard</th><th>Enterprise</th><th>Datacenter</th></tr> | |||
<tr><th>Protsessorite arv</th> <td> 1 </td><td> 2 </td><td>4 </td> <td> 4 </td><td> 8 </td><td> Operatsioon süsteemi maksimum</td></tr> | |||
<tr><th>Maksimaalne mälukasutus</th> <td> 1GB </td><td> 4GB </td><td>64GB</td> <td> 64GB </td><td> 2TB </td><td> Operatsioon süsteemi maksimum</td></tr> | |||
<tr><th>Maksimaalne andmebaasi suurus</th> <td> 10GB </td><td> 524PB </td><td>524PB</td><td>524PBB </td><td> 524PB </td><td> 524PB</td></tr> | |||
<tr><th>Tabelite ja indeksite partitsioneerimine</th> <td> Ei </td><td> Ei </td><td>Ei</td> <td>Ei </td><td> Jah </td><td> Jah</td></tr> | |||
<tr><th>Indekseeritud vaated </th> <td> Ei </td><td> Ei </td><td>Ei</td> <td>Ei </td><td> Jah </td><td> Jah</td></tr> | |||
<tr><th>Andmete tihendamine </th> <td> Ei </td><td> Ei </td><td>Ei </td> <td>Ei </td><td> Jah </td><td> Jah</td></tr> | |||
<tr><th>Ressursi haldur </th> <td> Ei </td><td> Ei </td><td>Ei </td> <td>Ei </td><td> Jah </td><td> Jah</td></tr> | |||
<tr><th>Parallel index operations </th> <td> Ei </td><td> Ei </td><td>Ei </td> <td>Ei </td><td> Jah </td><td> Jah</td></tr> | |||
<tr><th>Parallel consistency checks (DBCC) </th> <td> Ei </td><td> Ei </td><td>Ei </td> <td>Ei </td><td> Jah </td><td> Jah</td></tr> | |||
<tr><th>Enhanced read-ahead scan </th> <td> Ei </td><td> Ei </td><td>Ei </td> <td>Ei </td><td> Jah </td><td> Jah</td></tr> | |||
<table> | |||
==Andmebaasi loomine== | ==Andmebaasi loomine== | ||
Andmete hoiustamiseks andmebaasis, tuleb see enne luua. Selle protsessi käigus tehtud otsused mõjutavad väga palju tulevikus jõudlust ja ressursikasutust. Algfaasis tehtud valed valikud mõjuvad halvasti nii andmebaasi kui seda kasutavale rakenduse kiirusele. | |||
Oluline on andmebaasi loogiline ülesehitus, kuid tähelepanu tuleb pöörata ka kindlasti veergude definitsioonidile, mis tuleb määrata korrektselt ja loogiliselt. Näiteks reaalarvulised väärtused peavad olema reaalarvu tüüpi, tekstina neid hoides raisatakse ressurssi ning andmete lugemisel peab neid üldjuhul kasutamiseks teisendama vajalikku vormingusse. | |||
Samuti tuleb veerutüüpide loomisel alati läbi mõelda, kui täpseid andmeid nõutakse. Lihtne näide selle kohta on kuupäevad, mida kasutatakse alati väga palju. Näiteks registreerimaks uue sissekande loomise kuupäeva. Tihti kasutatakse andmebaasis kuupäeva tüübiks automaatselt ''DateTime'', mis võtab ruumi 8 baiti ja täpsuseks kolm millisekundit. Kuid enamasti ei ole selline täpsus vajalik ning väiksema täpsusega andmete hoiustamiseks ja töötlemiseks kulub vähem ressursse. Samas on olukordi, kus väärtuste suur täpsus on kriitiline, kuid kindlasti leidub rohkem situatsioone, kus piisab ka väiksemast täpsusest. | |||
Näiteks uudisteportaalides on uudiste avaldamisajad tihti märgitud ainult kuupäeva koos kellaajaga, mis on minutitäpsusega. Viimase jaoks on sobiv ''SmallDateTime'', mis on minuti täpsusega ja lisaks võtab poole vähem ruumi (4baiti). Lisaks on sellisel juhul olemas vajalikus vormingus kuupäev ning seda ei pea hakkama veebirakenduses andmete väljaküsimusel ümber hakkama vormindama. | |||
Näiteks | Andmebaasi loomisel tuleb säilitada paindlikus. Näiteks tabelis võtab ''tinyint'' primaarvõtme väljana 4 korda vähem ruumi võrreldes ''Int'' tüüpi veeruga, kuid sellesse tabelisse saab luua see tõttu ka 256 sissekannet. | ||
Samasuguseid näiteid leidub kõigi andmetüüpide kohta. Seega peaks enne tabelite loomist ja veergude tüübi määramist tutvuda konkreetse andmebaasimootori dokumentatsiooniga ja analüüsida, milliseid võimalusi võimalused on olemas. Näitena võib tuua eelpool mainitud kuupäevade tüübi valimise, kuna ''SmallDateTime'' on saadaval alates SQL Server 2008 versioonist. | |||
===Kordumatute väärtustega väljad andmebaasides=== | |||
Andmebaasi loomisel tuleb otsustada, millist tüüpi on primaarvõtme veerud. Tihti on nendeks ''INT'' või ''uniqueidentifier''. Esimene neist esindab täisarvulisi arve ja teise puhul on tegemist kordumatute väärtustega, mis on 16 baidised globaalsed identifikaatorid (GUID- Global Unique IDentifier). Need esitatakse kujul ''xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'', kus iga x tähistab üht tähte või arvu kuueteistkümnendsüsteemist.<br /> | |||
''Siia selgitus, milleks sellised väljad andmebaasides üldse kasutusel on ning mis on INT ja mis GUID'' | |||
Arvestades kui palju kordumatu väärtusega identifikaator ruumi võtab, võrreldes täisarvuga, võib selle kasutamine tunduda ebaratsionaalne. Siiski on sellel täisarvu ees ka mõned eelised.Näiteks on see alati unikaalne, kuid täisarv on unikaalne ainult ühes tabelis. Samuti on selle kasutamisega välistatud võimalus, et relatsioonilises andmebaasis viiakse omavahel kokku tabelite veerud, mis tegelikult ei ole seotud. Lisaks ei saa ''GUID'' kunagi otsa, kuid täisarvulise tüübi kõige suurem väärtus on 9 223 372 036 854 775 807, kui tegemist on ''bigint'' 'iga ja sellel juhul võtab see ruumi 8 baiti. [http://msdn.microsoft.com/en-us/library/ms187745.aspx] | |||
Üheks kordumatu väärtusega välja puuduseks on see, et selle kasutamine võib vähendada klasterdatud indeksiga saavutatud jõudlusevõitu, kui selle genereerimine toimub väljaspool andmebaasi. Iga uus sissekanne nõuab indeksite uuendamist ja seetõttu võib selle kasutamine kutsuda esile indeksi lehtede poolitusprobleeme ja nende fragmenteerumist, kuna loodud võtme väärtus ei pruugi olla viimane ja sellele tuleb leida õige koht. See nõuab aga kõigi seniste võtmete uuesti sorteerimist. Alates SQL Server 2005 versioonist saab selle vältimiseks kasutada funktsiooni ''NewsequentialID()'', mis tagab, et iga järgmine globaalne identifikaator on eelmisest suurem. Seega ei tule uus sissekanne mitte indeksite lehe keskele, vaid läheb alati viimaseks. Tuleb arvestada ka asjaoluga, et kuna see kasutab rohkem mälu, siis tekib indekseerimisel rohkem lehti ja nende uuendamine on kulukam kui täisarvulise tüübi puhul. | |||
==Päringute analüüs== | ==Päringute analüüs== | ||
Kirjete lisandumisel andmebaasi kasvab selle suurus ja ka päringute täitmiseks hakkab kuluma rohkem aega. Mingil ajahetkel võib tekkida situatsioon, kui andmete leidmiseks kulub liiga palju aega. See on aga selge märk sellest, et tehtavaid päringuid tuleks analüüsida ja seejärel optimeerida. | |||
Alljärgnev päring aitab otsustada, millised päringuid andmebaasis võivad vajada optimeerimist. | |||
<source lang="sql"> | |||
-- alljärgneva päringuga saad lugeda protseduur cache'i sisu | -- alljärgneva päringuga saad lugeda protseduur cache'i sisu | ||
-- saadav tabel sisaldab küllalt infot otsustamaks, millised protseduurid või päringud kulutavad serverit | -- saadav tabel sisaldab küllalt infot otsustamaks, millised protseduurid või päringud kulutavad serverit | ||
Line 100: | Line 262: | ||
--NB! Viimases veerus saadud tabelis on XML kujul Query Plan | --NB! Viimases veerus saadud tabelis on XML kujul Query Plan | ||
--Salvesta see laiendiga sqlplan ja ava Management Studios - ja imesta : | --Salvesta see laiendiga sqlplan ja ava Management Studios - ja imesta :) | ||
Selle abil saab | </source> | ||
(http://www.sarv.ee/ftp/henn/SQL/Proc%20cache%20statistika.sql) | |||
Selle abil saab sorteerida SQL päringuid kolmel erineval viisil: | |||
# täitmiskordade arvu järgi | |||
# päringu täitmiseks kokku kulunud aeg | |||
# päringu täitmiseks kulunud kõige suurem aeg. | |||
Head kandidaadid on päringud, mida täidetakse kõige sagedamini, sest nende parandamine annab tihti lõppkokkuvõttes suurema võidu. Näiteks, olgu meil kaks päringut,milledest esimest täidetakse päevas kümme ja teist tuhat korda. Optimeerides neist esimest, paraneb kiirus ühe sekundi ja teise puhul saja millisekundi võrra. Kogu ajaline võit ühe päeva kohta on aga tegelikult vastavalt kümme sekundit ja poolteist minutit. | |||
Konkreetse päringu analüüsimiseks saab kasutada SQL Serveri päringu täitmisplaani ''(Query Execution Plan)''. See näitab graafiliselt, kui palju mingi päringu täitmine aega võtab ja milliseid operatsioone selle käigus läbi viiakse. Kuvatavat plaani tuleb lugeda paremalt vasakule ja see lihtsustab päringus probleemsete kohtade leidmist. | |||
==Päringute optimeerimine== | ==Päringute optimeerimine== | ||
Info saamiseks andmebaasist tehakse päringuid, kus vastavalt seatud tingimustele väljastatakse | Info saamiseks andmebaasist tehakse päringuid, kus vastavalt seatud tingimustele väljastatakse neile vastavad kirjed. Nende loomisel tuleks jälgida mõningaid lihtsaid võtteid, et vältida üleliigset ressursi raiskamist. | ||
Kirjete pärimisel peab alati kirjeldama, milliseid veerge soovitakse selle tulemusena saada. Näiteks SELECT *(vali kõik veerud) mõjub jõudlusele negatiivselt: kui tabelis on kümme veergu, kuid vaja läheb neist ainult kahte. Sellisel juhul on tegemist ebavajaliku ressursiraiskamisega kahel põhjusel: 1)andmebaas saadab rakendusele rohkem infot kui vaja, 2) muudab indekseerimise keeruliseks. | |||
Tingimuste kirjutamisel tuleks alati küsida seda, mida tahetakse. Mitte vastupidi. | |||
Kõiki päringuid peaks hoidma andmebaasile võimalikult lähedal, kuna nii saadakse neile ka kiirem vastus, sest need asuvad andmetele lähemal võrreldes rakendusega. | |||
== | ==Talletatud protseduurid== | ||
Talletatud protseduurid on põhimõtteliselt kogum juba varem valmis kirjutatud SQL päringuid, mis on koondatud üheks hallatavaks blokiks. Igat loodud protseduuri kompileeritakse (toimub automaatselt) ühekorra ja peale seda luuakse päringu täitmise plaan, mida hoitakse mälus. Edaspidi võetakse päringu täitmiseks see plaan juba mälust ning seetõttu on ka nende täitmine kiirem. http://www.tech-faq.com/stored-procedure.html + SQL Server Bible(Lk 610) | |||
'''Kas peaks siia hoopis loetelu tekitama? Nagu punkt1..punkt2.. punkt3'''<br /> | |||
Hästi kirjutatud protseduurid on väga kiired, kuna nad asuvad andmete lähedal. Neid on lihtne testida ja hallata võrreldes veebirakendustes loodud päringutega. Talletatud protseduurid on turvalised, kuna kasutavad parameetreid, mis antakse neile kaasa ja nii kaob SQL injektsiooni oht. Rakenduse loojatel on samuti lihtsam kutsuda välja protseduur, mille sisendiks antakse parameetrid, kui kirjutada seda päringut veebirakenduses. SQL Server Bible (607) | |||
Kasutades protseduure on lihtsam jälgida päringute täitmist ja ajakulu, võrreldes tavalise SQL päringuga, mis tuleb väljaspoolt andmebaasi. Kuna talletatud protseduuri väljakutsumiseks antakse kaasa ainult parameetrid, siis on ka edastatav andmemaht väiksem. | |||
Lisaks tuleks vältida kursoreid. Kuigi nad on väga paindlikud ja võimaluste rohked, tuleb nende kasutamisel maksta ränka hinda jõudluses. Kui protseduurides | Kirjutades protseduure on hea praktika lülitada COUNT välja kasutades käsku <source lang="sql">SET NOCOUNT ON</source>. Viimasega võib sõltuvalt päringu keerukusest võita kuni 17% selle täitmise kiirusest. Vaikimisi on NOCOUNT välja lülitatud ja seetõttu saadetakse päringu tulemusele kaasa ka alati kirjete arv, mis selle tulemusena leiti. ( SQL Server 2008 Bible ..622 ). | ||
(LK | |||
Lisaks tuleks vältida kursoreid. Kuigi nad on väga paindlikud ja võimaluste rohked, tuleb nende kasutamisel maksta ränka hinda jõudluses. | |||
Kui neid kasutatakse protseduurides, siis optimeerimiseks tuleks alustada nende eemaldamisest. | |||
<br/>'''Kas võin tuua näite SQL Server Bible'st?''' | |||
==Indekseerimine== | ==Indekseerimine== | ||
Indekseerimine on nagu raamatu sisukord. Kui soovitakse leida vajalikku infot, vaadatakse eelkõige sisukorda ning leitakse õige koht. Samamoodi käiakse pidevalt andmebaasist infot pärimas. Tabel ilma indeksita on nagu raamat sisukorrata - millegi leidmiseks peab lehitsema läbi terve raamatu, et leida õige koht, mida otsitakse. Loomulikult on see ajaliselt kulukas protsess. Kui andmebaasis on tabelid õigesti indekseeritud toimub otsimine nagu raamatu sisukorrast (kiiresti). | |||
Indekseid on kahte tüüpi - klasterdatud ja klasterdamata. | Indekseid on kahte tüüpi - klasterdatud ja klasterdamata. | ||
Klasterdatud indekseerimiseks on ideaalsed väljad tabelite primaarvõtmed kahel põhjusel: 1) see väli on alati unikaalne 2)infot otsitakse tihti selle võtme järgi. Vaikimisi luuakse primaarvõtme veerule alati klasterdatud indeks. Selle loomiseks käsitsi tuleb kasutades SQL lauset: | Klasterdatud indekseerimiseks on ideaalsed väljad tabelite primaarvõtmed kahel põhjusel: 1) see väli on alati unikaalne 2) infot otsitakse tihti selle võtme järgi. Vaikimisi luuakse primaarvõtme veerule alati klasterdatud indeks. Selle loomiseks käsitsi tuleb kasutades SQL lauset: | ||
CREATE UNIQUE CLUSTERED INDEX index_id ON TABLE (veeru_nimi) | <pre>CREATE UNIQUE CLUSTERED INDEX index_id ON TABLE (veeru_nimi)</pre> | ||
Tabeliveerg millele see luuakse, peab olema alati unikaalne. | Tabeliveerg, millele see luuakse, peab olema alati unikaalne. | ||
Mitte klasterdatud indekseerimise puhul ei pea olema | Mitte klasterdatud indekseerimise puhul ei pea väli olema unikaalne. Luuakse lausega: <source lang="sql"> CREATE INDEX voti ON tabeli_nimi(veeru_nimi)</source>. Sellest on ainult siis kasu, kui me valime ainult konkreetse välja, mis on klasterdamata indeksisse määratud. Kui lisaks sellele on vajalik valida veel välju, tuleks kasutada kaetud indekseerimist ning lisada vajalikud väljad. Selleks tuleb kasutada lauset: <pre>CREATE INDEX v0ti ON tabeli nimi(veerg) include ( tabeli_veerg1, tabeli_veerg2,..).</pre> Sobib eriti veergudele, kus kasutatakse ''GROUP BY, COUNT(*)'' päringuid. | ||
Indekseerimiseks ei sobi väljad, mis on väga mahukad. Näiteks nVarchar(200), mis võtab palju ruumi ja indeksite loomine on mahukas protsess. | Indekseerimiseks ei sobi väljad, mis on väga mahukad. Näiteks nVarchar(200), mis võtab palju ruumi ja indeksite loomine on mahukas protsess. | ||
Indekseerides tabeli veerge | Indekseerides tabeli veerge ilma analüüsita, võib see mõjuda jõudlusele hoopis negatiivselt, kuna õigete ridade leidmiseks peab ikkagi tegema lisapäringuid. Selle vältimiseks tuleks jälgida päringu täitmise plaani, mis näitab, kuidas päringuid läbi viiakse ja kas loodud indekseid kasutatakse. Nii võib leida kohti, kus need on küll loodud, kuid küsitakse rohkem kirjeid kui indeksiga kaetud on. | ||
Indekseerimisel tuleb arvestada sellega, et nende loomisel peab maksma natuke hinda ka jõudluses. Sellest tulenevalt tuleks kaasata indeksitesse minimaalselt välju. Mida rohkem on välju, seda kulukam on indeksite uuesti arvutamine, mis leiab aset iga DDL käsu puhul. Indeksite tabel koosneb lehtedest ja lisades uue sissekande tuleb lehed uuesti luua. Eriti halvasti mõjub see siis, kui uus sissekanne tuleb indeksi lehtede keskele. Viimane eeldab lehtede uuesti loomist ja nende poolitamist. Seetõttu tuleb hoolikalt kaaluda, kus kasutada rühmitatud indekseid. | |||
Alates SQL Server 2008 versioonist on võimalik kasutada filtreeritud indekseerimist, mis tähendab, et klasterdamata indeksite loomiseks kasutatakse andmetest ainult mingit osa, mis vastab seatud tingimustele. Selle loomiseks on lause: CREATE INDEX index_id ON tabeli_nimi(tabeli_veerg) WHERE | Alates SQL Server 2008 versioonist on võimalik kasutada filtreeritud indekseerimist, mis tähendab, et klasterdamata indeksite loomiseks kasutatakse andmetest ainult mingit osa, mis vastab seatud tingimustele. Selle loomiseks on lause: | ||
<pre>CREATE INDEX index_id ON tabeli_nimi(tabeli_veerg) WHERE tingimus </pre> . Vajadusel saab ka siin kasutada kaetud indekseerimist. | |||
==Transaktsioonid== | ==Transaktsioonid== | ||
http://msdn.microsoft.com/en-us/library/ff647793.aspx#scalenetchapt14%20_topic9 | http://msdn.microsoft.com/en-us/library/ff647793.aspx#scalenetchapt14%20_topic9 | ||
Valesti kirjutatud transaktsioonid | Valesti kirjutatud transaktsioonid mõjuvad andmebaasi tööle negatiivselt. Selle vältimiseks on levinud praktikad: | ||
tuleks | tuleks vältida pikki transaktsioone, kuna nende ajal toimub tabelis lukustamine. Soovitatav on valideerida enne transaktsioone juba rakenduses andmed, et vältida transaktsiooni ajal vigade tekkimist, mis pikedab neid. Lisaks ei tohiks transaktsioone alustada enne, kui kõik vajalikud andmed on olemas, kuna lukustus lõpeb alles siis, kui kõik andmed on saadetud. Halb näide on näiteks see, kui alustada transaktsiooniga, kuid selle edukaks lõppemiseks on vaja veel kasutaja poolt sisendit. Tabel on lukus seni, kuni kasutaja on sisendi andnud. | ||
Ummik(''Deadlock'')on situatsioon, kus üks transaktsioon ootab teise ja teine esimese taga. Kindlasti tuleks sättida sellele aegumise piir, kuna vaikeseadetes võivadki need üksteise järgi põhimõtteliselt ootama jääda. Samuti tuleks sättida parallelism üheks. | |||
SQL Server Bible 1382. | SQL Server Bible 1382. | ||
== | ==Täistekstiotsing== | ||
SQL | Tihti on vaja lõppkasutajatele võimaldada info otsimist. Kuna enda otsingusüsteemi loomine on kulukas protsess, siis sobib seda asendama alguses SQL Serveri ''FullTextSearch'' funtsionaalsus. Viimast saab kasutada alates Standard väljaandest ning see töötab indekseerimise põhimõttel. Antud lahendus pole mõeldud otseselt otsingumootoriks, kuid see on väga hea jõudlusega ning täidab igati oma põhiülesannet, hoides samal ajal ressursikasutuse madalana. Kindlasti tuleks seda eelistada algelisele otsingule, kus kasutatae LIKE operaatorit, mis on aeglane. | ||
Sama lahendus on hetkel kasutusel Eesti Rahvusringhäälingu .NET portaalide otsingusüsteemides ja on ennast igati õigustanud. | |||
==Andmebaasi konfigureerimine== | ==Andmebaasi konfigureerimine== | ||
Parimate praktikate kohaselt soovitatakse jätta | Parimate praktikate kohaselt soovitatakse jätta paljudele seadetele vaikimisi väärtused. Nii töötab server kõige optimaalsemalt ning nende muutmisel võib olla effekt jõudlusele hoopis negatiivne. | ||
'''Startup Manager''' | '''Startup Manager''' | ||
Kui soovida | Kui soovida andmebaasist kätte saada maksimum, siis võib SQL Server Configuration Manager'is lisada Startup Parameters alla parameetri -x, mis võimaldab maksimaalselt jõudlust. Selllel on aga üks väga suur miinus. Nimelt lülitatakse kõik monitoorimisvõimalused selleks välja ja jõudlusprobleemide jälgimine ja otsimine muutub peaaegu võimatuks. | ||
'''Ühenduste automaatne sulgemine(Auto Close)''' | '''Ühenduste automaatne sulgemine''(Auto Close)''''' | ||
Ühenduste | Ühenduste automaatse sulgumise korral vabastab SQL SERVER kõik selle andmebaasi ressursid, peale viimase aktiivse ühenduse sulgumist (sh päringu täitmise plaanide ja kompileeritud talletatud protsetuuride kustutamist). Vabanenud ressursse saavad kasutada teised andmebaasid. Pealtnäha tundub selline tegevus optimaalne, kuid tegelikult on see kindel viis, kuidas SQL Serveri töö hävitada. Paljud rakendused sulgevad ja avavad ühendusi korduvalt. Uute ühenduste tekkimisel tuleb uuesti laadida, kompileerida protseduurid ja arvutada päringu läbiviimise plaanid. See tõttu peaks ühenduste automaatne sulgemine olema keelatud, mis on ka kõigis SQL Serveri versioonides vaikimisiväärtuseks, välja arvatud SQL Express väljaandes. | ||
Ühenduste automaatset sulgemist saab kontrollida graafiliselt Management Studiost või käsuga: <source lang="sql">ALTER DATABASE ANDBEMAASINIMI SET auto_close ON/OFF.</source> | |||
See peaks olema lubatud ainult siis, kui tegemist on andmebaasiga, mis hoiab endas arhiivi ja kasutatakse väga vähe. | |||
'''Automaatne kahanemine (Auto Shrink)''' | '''Automaatne kahanemine ''(Auto Shrink)''''' | ||
Kui see võimalus on sisselülitatud, siis juhul kui andmebaasil on üle 25% vaba ruumi, toimub andmete ja logifailide kahandamise operatsiooni. See protsess on kulukas ja samas hakkavad need failid hiljem nagunii kasvama. See põhjustab faili fragmenteerumist operatsioonisüsteemi tasandil. Selle saab välja lülitada käsuga: | |||
<source lang="sql">ALTER DATABASE Andmebaasinimi SET AUTOSHRINK OFF;</source> | |||
SQL Server Bible 2008 lk 920 | |||
=ASP.NET tehnoloogiast tulenevad optimeerimisvõimalused= | =ASP.NET tehnoloogiast tulenevad optimeerimisvõimalused= | ||
== | ==Konfiguratsioon== | ||
web.config failis | Konfiguratsiooni hoitakse web.config failis. Selle näol on tegemist infoga veebirakenduse seadistuse kohta. Näiteks: andmebaasiga ühenduse loomiseks vajalikud parameetrid või kuidas toimub rakenduse kompileerimine. ASP.NET kasutab selles failis olevat infot, et luua rakenduse ülesehitus. | ||
Lisaks tasub web.config faili lisada | Kui testkeskkonnas siluda rakendust, peaks kindlasti selles failis parameetri "compilation debug" väärtus olema true. Vigade esinemise korral on sel juhul neid lihtne leida. Rrakenduse ''live ''serverisse tõstmisel peab jälgima, et silumine oleks kindlasti välja lülitatud. Vastasel juhul kompileeritakse pidevalt veebirakendust iga lehe laadimise ajal uuesti ja see omakorda kasvatab protsessori ja mälu kasutust. Kõige kindlam viis sellise olukorra vältimiseks on muuta serveris asuvat machine.config faili ja lisada parameeter ''deployment retail="true"''. Nii on kindel, et ükski veebiaplikatsioon ei kasuta antud serveris silumist. Ainukeseks miinuseks selle puhul on, et vea ilmnemisel ei kuvata vea täpset asukohta (rea numbrit ja veakirjeldust). | ||
Lisaks tasub web.config faili lisada väljundipuhvri erinevad profiilid. Sellega saab määrata, kui kaua lehte serveri mälus hoitakse. Kui rakendusele on tulemas suur koormus, saab ühest kohast muuta kõikide väljundite kehtivuse pikkust, mis kasutavad konkreetset profiili. | |||
==Viewstate== | ==Viewstate== | ||
Viewstate'i kasutatakse, et hoida väärtusi ASP.NET tööriistade(controls) objektide kohta. Lehe | Viewstate'i kasutatakse, et hoida väärtusi ASP.NET tööriistade (controls) objektide kohta. Lehe laadimisel genereerib ASP.NET ühe peidetud välja, mis kannab nime ''__VIEWSTATE'', kus on see info sees. Nii on võimalik antud väärtuseid kasutada ka peale kliendi-serveri vahelist suhtlust, kui toimub tagasipostitamine ''(postback)''. Hoides selles suurel hulgal andmeid, kasvab seetõttu ka lehe suurus ning selle laadimise aeg. Arvestama peab ka sellega, et lehe laadimisel tuleb viewstate'is olevaid andmeid serialiseerida ja deseriaaliseerida. Lisaks võib see vähendada mäluhalduse(GC) efektiivsust. Sellepärast tuleb selle kasutamisega olla ettevaatlik ja eemaldada kohtadest, kus seda vaja ei lähe, kuna see mõjub jõudlusele halvasti. Näiteks genereerivad kõige rohkem viewstate'i ASP.net enda tööriistad nagu ''Listview'' ja ''Gridview''. | ||
Lehel sisalduva viewstate'i hulga analüüsimiseks on hea tööriist ASP.NET ViewState Helper, mis töötab Firefoxi ja Internet Exploreriga. Selle abil on võimalik näha, kui suure osa moodustab kogu lehe suurusest viewstate. | Lehel sisalduva viewstate'i hulga analüüsimiseks on hea tööriist ASP.NET ViewState Helper, mis töötab Firefoxi ja Internet Exploreriga. Selle abil on võimalik näha, kui suure osa moodustab kogu lehe suurusest viewstate. | ||
Vaikimisi on see ASP.NET'is igal pool | Vaikimisi on see ASP.NET'is igal pool sisse lülitatud. Soovitatav on see välja lülitada kohtades, kus ei toimu serveri poolseid kontrolle ja ei kasutata tagasipostitamist (postback). Seda saab välja lülitada erinevatel tasemetel: serveris (machinge.config), veebirakenduses (web.config), lehel <source lang="asp"><%@ Page EnableViewState="false" %> </source>kui ka ASP.NET tööriistades endas (EnableViewstate=false). | ||
Kui lehel on lubatud viewstate ja toimub tagasipostitus (postback), siis tuleb seda kontrollida kasutades ''IsPostBack()'' meetodit. Viimane teeb kindlaks, kas tegemist on tagasipostitamisega ''(postback)''. Kui on, siis pole vajadust enam andmeid uuesti pärida, vaid kasutada juba olemasolevaid ja võtta need viewstate'is. | |||
Kui lehel on lubatud viewstate ja toimub postback, tuleb seda kontrollida kasutades IsPostBack() meetodit | |||
==ASP.NET enda tööriistad== | ==ASP.NET enda tööriistad== | ||
Enimkasutatavad tööriistad on tihti GridView, Listview ja Repeater. Neid kasutatakse tihti erinevate vaadete loomiseks. Esimesed kaks neist genereerivad suurel hulgal viewstate'i, sisaldes väga palju funktsionaalsust. Selle tõttu peab alati valima, milliseid tööriistu kasutada. Kui eesmärgiks on tavalise listi loomine (näiteks uudiste), siis peab kindlasti viewstate'i keelama ja kasutama võimalusel ''Repeater''' it, kuna ''ListView'' funktsionaalsust tegelikult vaja ei lähe. | |||
Nende kasutamisel tuleks tähelepanu pöörata väärtuste kuvamise viisile. Levinud on selleks kasutada võimalust: <source lang="asp"><%#Eval("fieldname")%></source>, mis defineerib välja nime, kuskohast väärtust päritakse. Seda on lihtne kasutada, olenemata sellest, kas tegemist on objektide listiga või ''DataTable'''iga. Tegelikult tuleb sel juhul maksta hinda jõudluses, kuna küsitava välja tüüp ei ole tegelikult defineeritud ja selle kindlaks tegemiseks kasutatakse peegeldust (reflection). Nii tuleb 10 rea väärtustamiseks teha Eval operatsiooni tegelikult 20 korda, kuna esialgu pole teada, millist tüüpi andmetega on tegu. Parem variant on viidata kohe klassile, kust otsitav väli pärit on. Nagu näiteks: | |||
<source lang="asp"> | |||
<%#((MyClass)Container.DataItem).field1%> <!-----Klass----!> | |||
<%#((DataRowView)Container.DataItem).field1%>.<!---DataTable---!> | |||
</source> | |||
'''ASP.NEt Site Performance 76''' | |||
Ainuüksi 10 rea lisamisel võib kiiruse vahe olla enam kui kümnekordne, viimase variandi kasuks mõõdetuna ticksides. Selle kasutamisel peab arvestama, et muutes näiteks klassinime, tuleb muutma seda ka kohas, kus päritakse välja väärtuseid. | |||
ASP.NET genereerib automaatselt HTML'i kõikidele väljadele ID'd, kui need on ka koodis määratud. Näiteks kui kasutada pildikomponenti parameetritega <source lang="asp"><asp:Image ID="imgMainItem" runat="server"/></source>, siis sõltuvalt selle sügavusest lehtede hierarhias võib peale kompileerimist HTMLi vaadates näha, et antud välja ID'ks on saanud hoopis <source lang="asp">id="ctl00_leftColumn_ctl00_Vaikekategooria3_imgMainItem"</source>. Tegemist üpriski mahuka nimetusega. Kui aga tegelikkuses seda id'd ei vajata, siis peaks jätma selle määramata. Mahuka esilehe puhul on sellega võimalik hoida päris palju ruumi kokku. Kui siiski vajatakse ID'd, võib selle peale kasutamist ära nullida. Nnäiteks: | |||
<source lang="csharp"> | |||
//.... | |||
imgMainItem.Src="pilt.jpg"; | |||
imgMainItem.ID=null; | |||
//.... | |||
</source> | |||
==Puhver== | |||
Andmete talletamine puhvris on üks lihtsamaid viise, kuidas muuta veebirakenduse ja ka andmebaasi tööd kiiremaks. See võimaldab hoida enimkasutatavaid objekte mälus. Sellest andmete kättesaamine on lihtsam ja kiirem, kui selle pärimine pidevalt andmebaasist või kuskilt mujalt. ASP.NETis on kasutusel väljundi puhverdamisliides hoidmaks mälus objekte ning väljundipuhver, kus salvestatakse serveri mällu terve leht. Nende mõlema meetodi kasutamisel peab arvestama, et vajalike andmete/lehtede hoiustamiseks kasutatake serveri mälu. Seetõttu peab läbi mõtlema, milliste andmete talletamine mälus on kriitiline. Seda eriti juhul, kui serveril on mälu vähe. Head kandidaadid puhverdamiseks on lehed/andmed, mida kasutatakse kõige rohkem või mille kätte saamine on väga kulukas protsess. Enamasti on selleks näiteks esileht ja mõned suuremad listid ning otsingutulemused. | |||
Väljundi puhverdamisliides ja väljundipuhver on küll kaks erinevat mõistet, kuid põhimõte on neil siiski sarnane. Mõlemale on võimalik ette anda aeg, kui kaua aega neid serveri mälus hoitakse. Lisaks saab mõlema puhul kasutada ''SqlCacheDepencyt'', mis võimaldab jälgida, kas andmebaasitabelites on muudatusi toimunud. Mälust kustutakse andmed, kui jälgitavas tabelis toimub muudatus.'''Selle toimimiseks peab andmebaasis lubama tabelitel ''SqlCacheDependency'' ja ka web.config failis kajastama seda.''' Selles saab määrata, kui tihti kontrollitakse, kas andmebaasitabelites on toimunud muudatusi. | |||
http://www.asp.net/data-access/tutorials/using-sql-cache-dependencies-vb | |||
http://msdn.microsoft.com/en-us/library/system.web.caching.sqlcachedependency.aspx | |||
=== | Võimalus on kasutada ka mitme tabeli jälgimist. Soovitatav on vaadelda tabeleid, milles ei toimu tihti muudatusi. Vastasel juhul on puhver pidevalt tühi ja andmete saamiseks tuleb siiski päringuid teha. Sellisel juhul tuleks anda ajaline intervall, mille tagant andmeid uuendatakse. http://msdn.microsoft.com/en-us/library/system.web.caching.sqlcachedependency.aspx. | ||
Shared="true/false" - saab kasutada ainult usercontrollide puhul. Kui true, siis cache'itakse see kõikidel lehtedel. | Väljundipuhvri kasutamine on kiirem, kuna selle puhul on lehe töötsükkel lühike. Alguses kontrollitakse, kas leht on serveri mälus olemas ja kui see eksisteerib seal, siis see saadetakse kasutajale. Väjundi puhverdamisliidese puhul aga toimub terve lehe elutsükkel. (See on kirjeldatud peatükis ASP.NET veebirakenduse põhikomponendid ja töötsükkel) | ||
CacheProfile="profiilinimi" - | ===Väljundipuhver=== | ||
SqlDependency ="adnmebaasi/tabeli paar" - defineeritakse andmebaasi /tabeli paarid, mille muutumise korral leht serveri mälust kustutakse. | http://msdn.microsoft.com/en-us/library/xadzbzd6.aspx | ||
http://msdn.microsoft.com/en-us/library/hdxfb6cy.aspx | Väljundipuhvri kasutamisel salvestatakse terve dünaamiliselt loodav leht serveri mällu. Peale seda kuvatakse seal olevat lehte. Seda saab kasutada nii terve .aspx lehtede salvestamiseks kui ka usercontrolide puhul. Väljundipuhvri jaoks tuleb lisada järgnev kood lehe ülaossa: | ||
<source lang="asp">< %@ OutputCache Duration="60" VaryByParam="None" % ></source> | |||
Need kaks parameetrit on alati kohustuslikud. Kestvus(''Duration'') näitab kui pikka aega lehte serveri mälus hoitakse ja ''VarByParam'' parameetriks saab anda päringustringi(d). | |||
Lisaks on levinumad parameetrid veel: | |||
<ul> | |||
<li>Shared="true/false" - saab kasutada ainult usercontrollide puhul. Kui true, siis cache'itakse see kõikidel lehtedel. </li> | |||
<li>CacheProfile="profiilinimi" - konfigratsuoonfailis asuv väljundpuhvri profiil. </li> | |||
<li>SqlDependency ="adnmebaasi/tabeli paar" - defineeritakse andmebaasi /tabeli paarid, mille muutumise korral leht serveri mälust | |||
kustutakse. | |||
http://msdn.microsoft.com/en-us/library/hdxfb6cy.aspx</li> | |||
<li>VarByCustom ="nimi" - võimaldab kasutajal luua endal puhverdamise meetod </li> | |||
<li>VarByParam="parameeter" - saab anda ühe või mitu päringustringi väärtust, mille põhjal leht salvestatakse väljundpuhvrisse. | |||
</ul> | |||
''VaryByCustom'''i, kasutamiseks tuleb Global.asax failis ülekirjutada GetVarByCstomString meetod: | |||
Näiteks: | Näiteks: | ||
<source lang="csharp"> | |||
public override string GetyVarByCustomString(HttpContext context, string custom){ | public override string GetyVarByCustomString(HttpContext context, string custom){ | ||
if(custom=="weekday"){ | if(custom=="weekday"){ | ||
return .... | return .... | ||
}else{ | }else{ | ||
return | return base.GetVarbyCustomString(context, custom) | ||
} | } | ||
} | } | ||
ASP.NET ei hooli stringi tegelikust sisust, vaid kontrollib seda, kas vastav stringi väärtusega leht on juba serveri mällu salvestatud. Kui on, siis serveeritakse leht serveri mälust, vastasel juhul lisatakse uus lehe koopia mällu | </source> | ||
ASP.NET ei hooli stringi tegelikust sisust, vaid kontrollib seda, kas vastav stringi väärtusega leht on juba serveri mällu salvestatud. Kui on, siis serveeritakse leht serveri mälust, vastasel juhul lisatakse uus lehe koopia mällu. | |||
'''Kas selle alumise möla peaks ära kustutama? Tegelikult ei ole üldse hea lahendus ju... Või mis?''' | |||
Olen seda saab kasutanud näiteks feedi cache'imiseks, mille loomine oli väga kulukas ja mida tohivad näha ainult teatud IP aadressitega kliendid. Tavalise OutPutCache'i lisamine on välistatud, kuna kui võõra IP'ga klient tuleb, näeb ta ikkagi feedi sisu, leht on serveri mälus ja outputcache'i puhul lehe eventeid ei käivtata. Teine halb asi, mis võib juhtuda on kui võõra IP'ga klient tuleb siis kui lehte pole veel serveri mälus.Sellel juhul aga läheb terve feed katki, kuna serveri mälllu salvestatakse leht, mis on tühi, kuna sel hetkl käis lehel keelatud IP'ga klient. Lahenduseks oli override'ida GetVarByCustomString meetod ja cache'ida leht IP põhiselt. | |||
== | ===Väljundi puhverdamisliides=== | ||
Cache API puhul ei hoita serveri mälus mitte tervet lehte, vaid soovitud väärtusi, mis lisatakse sinna koodifailis. Näiteks: | |||
<source lang="csharp">Cache.Insert("võti", "väärtus");</source>. Tihti on selleks list objektidest, ''DataTable'' või midagi muud sarnast. Lisamiseks kasutatakse võti/väärtus paari, millele saab lisaks kaasa anda aegumise intervall või sõltuvus andmebaasitabeli muudatustest (''SqlCacheDependency''). | |||
Võimalikud parameetrid, mida Cache.Insert meetodi sisendiks saab kasutada on: | |||
<ul> | |||
<li>Insert(String, Object) - Lisab objekti mällu.</li> | |||
<li>Insert(String, Object, CacheDependency) - Lisatakse objekt mällu ja arvestatakse Dependencyga nii faili kui andmebaasi puhul.</li> | |||
<li>Insert(String, Object, CacheDependency, DateTime, TimeSpan) - Lisatakse objekt mällu koos aegumisreeglitega. | |||
</li> | |||
</ul> | |||
http://msdn.microsoft.com/en-us/library/system.web.caching.cache.insert.aspx | |||
Selle abil saab vähendada väärtuste pärimiseks tehtavaid päringuid. Enne väljundipuhvrist informatsiooni välja võtmist, tuleb alati kontrollida, kas vastava võtmega on seal üldse midagi olemas, kuna vahepeal kustutakse serveri mälus hoiustatud väärtusi. See leiab aset näiteks juhtudkel, kui serveril on vähe mälu, objekt aegub või muutub dependency. | |||
Kontrollida saab näiteks nii: | |||
<source lang="csharp"> | |||
if(Cache[key]!=null){ | |||
} | |||
</source> | |||
http://msdn.microsoft.com/en-us/library/ms178597.aspx | |||
=.NET raamistiku vahenditest tulenevad optimeerimisvõimalused= | |||
Koodi optimeerimine ei puuduta ainult selle kirjutamist, vaid ka viisi, kuidas seda teha. Juba lihtsamate praktikate järgimine võib tagada rakenduse kiirema töötamise. | |||
Tuleks vältida kordusi, kuna see genereerib liiasust ja võtab ilmaasjata mälu. Objektid tuleks initsialiseerida võimalikult hilja:alles siis kui neid kasutatakse. Nende loomine võtab küll vähe aega, kuid nad allutavad endale seniks mälu kuni neid enam ei vajata. Seda teemat puudutab autor peatükis Mäluhaldus. | |||
Erinevate | ==.NET enda vahendite kasutamine== | ||
Erinevate andmetöötlusprotsesside jaoks tuleks eelistada .NET'i enda olemasolevaid meetodeid, kuna need on tihti kõige optimeeritumad. Väikeste andmehulkade puhul ei pruugi ajaline vahe välja paista, kuid mahukamate operatsioonide puhul võib olla see märgatav. | |||
''' | |||
Näiteks väga mahukate stringide liitmisel, tuleks kasutada ''StringBuilder''it ja tema ''append'' meetodit. | |||
<source lang="csharp"> | |||
string s = "TestSona"; | |||
string temp=""; | |||
for (int i = 0; i < 15000; i++) | |||
{ | |||
temp += s; | |||
} | |||
</source> | |||
Täitmiseks kulus: 0.7213204 sekundit. | |||
<source lang = "csharp"> | |||
StringBuilder sb = new StringBuilder(); | |||
string s = "TestSona"; | |||
for (int i = 0; i < 15000; i++) | |||
{ | |||
sb.Append(s); | |||
} | |||
</source> | |||
Täitmiseks kulus: 0.0003441 sekundit. | |||
Samad põhimõtted kehtivad ka teiste operatsioonide kohta nagu näiteks stringide ja kuupäevade võrdlus. | |||
SQL Site Performance lk 79 | |||
==Veahaldus== | |||
Veahaldus on kulukas protsess ja selle valesti kasutamine võib maksta väga valusalt kätte jõudluses. Näitena kasutab autor ''Guid'''i sõelumist ''(parse)''. Tegemist võib olla reaalse situtatsiooniga, kus päringustringist saadakse väärtus ja on vaja kontrollida, kas tegemist on õiget tüüpi muutujaga. Selleks on kaks võimalust: kasutada tavalist try-catch veahaldust või meetodit TryParse(). TryParse proovib sisendiks antud parameetrit parsida ja kui see õnnestub, siis tagastab ''true'' ja parsitud väärtuse. Kui see toimub edukalt, töötavad mõlemad variandid sama kiiresti. Kui see ei õnnestu, on TryParse tunduvalt kiirem. | |||
<pre>for(int i=0; i<5000; i++){ | |||
Guid temp; | |||
try | |||
for(int i=0; i< | { | ||
temp = Guid.Parse("asd-454-as23-a2322-asdasdasd-afgh123"); | |||
} | |||
catch | |||
{ | |||
} | |||
} | } | ||
for(int i=0; i< | for(int i=0; i<5000; i++){ | ||
Guid targetGuid; | |||
if(!Int32.TryParse("xyz", out | if(!Int32.TryParse("xyz", out asd-454-as23-a2322-asdasdasd-afgh123)){ | ||
} | } | ||
} | }</pre> | ||
Tulemus: Esimese variandi jaoks kulus 0.2146621 ticksi, ''TryParse'' jaoks 0.0010329 sekundit. Vahe on umbes kahesaja kordne. | |||
Lisaks on sellises situatsioonis try-catchi kasutamine väga väär, kuna see on siiski loodud ainult vigade töötlemiseks nagu näiteks andmebaasiühendus eavamine. Kindlasti ei tohiks kasutada seda programmis tingimuste täitmise kontrolliks, sellele tuleks eelistada kontrolle. | |||
Kasutades foreachi on küll mugav koodi kirjutada, kuid arvestades jõudlust ei ole see kõige parem variant, kuna listi läbikäimiseks kasutatakse | ==Tsüklid== | ||
Kasutades foreachi on küll mugav koodi kirjutada, kuid arvestades jõudlust ei ole see kõige parem variant, kuna listi läbikäimiseks kasutatakse enumeraatorit ja see tõttu on see ka kulukas. Sellele tuleks eelistada for tsüklit, mis on optimaalsem. Lisaks tuleks viimast kasutades hoiustada listi pikkus muutujas, et iga iteratsiooni ajal ei peaks seda uuesti arvutama, mis on küll väike, aga siiski ressursi raiskav operatsioon. Samuti ei tohiks küsida välja iga iteratsiooni ajal välja väärtusi, mis on kõik aeg konstantsed, vaid defineerida need enne tsüklit näiteks objektide puhul. ASP.NEt site performance Lk80 | |||
==Strukt ja klass== | |||
Võimalusel tuleks eelistada struktide kasutamist, kuna need annavad juurde jõudlust. Põhjuseks on nende erinevus mälukasutuses. Struktid paiknevad alati pinus(stack), peale meetodi täitmist kustutatakse need kohe ära. Klasside puhul on tegemist 'reference' tüüpi väärtustega, mille jaoks läheb lisaks vaja veel aadressi(tüüpobjektpointerit), sünkroniseerimisblokki(alati olemas), GC vajalikud väljad(bitid) ja alles siis on kirjeldatud väärtused. Näiteks juhul, kui on defineeritud strukt ja objekt, millel mõlemal on ainult üks väli ja see on täisarvu tüüpi, siis objekti puhul võtab üks täisarvu väärtus kolme täisarvu jagu ruumi. Strukt aga ainult ühe. | |||
Ka nende meetodite väljakutsumine on erinev, kuna | Ka nende meetodite väljakutsumine on erinev, kuna strukt on väärtustüüpi, siis teab kompilaator alati mis tüüpi väljaga on tegemist. Objekti meetodi väljakutsumisel viitab see aga tüübi tabelile. | ||
Struktidel on aga ka piirangud, kui neid kasutada ei saa. Nende puhul ei ole pärilust(inheritance) nagu klassidel. Lisaks ei saa seda olemasolevast klassist ega struktist tuletada, küll aga saab implementeerida ''interface'''ist. | |||
Struktidel on ka piirangud, | |||
http://msdn.microsoft.com/en-us/library/aa288471%28v=vs.71%29.aspx + hennu loeng. | http://msdn.microsoft.com/en-us/library/aa288471%28v=vs.71%29.aspx + hennu loeng. | ||
00:43 H.Sarv | 00:43 H.Sarv. | ||
==Listid== | |||
Kollektsioonide kasutamist tuleks alati võimalusel vältida, neile tuleks eelistada massiive, mis on kõige kiiremad. Kui see pole aga võimalik, on soovitatav kasutada Genereerikuid nagu näiteks List või Dictionary. Viimane on eriti kiire kui listist on vaja otsida konkreetseid väärtuseid, kuna tegemist on võti-väärtus paariga. Lisaks saab võtme välja abil välistada duplikaatide esinemist, kuna see peab olema unikaalne. Listi loomisel tuleks anda ette ka selle suurus. Kui seda mitte teha, siis peale seda kui listis saab kohtade arv täis, korrutatakse olemasolev list kahega ja pannakse see | Kollektsioonide kasutamist tuleks alati võimalusel vältida, neile tuleks eelistada massiive, mis on kõige kiiremad. Kui see pole aga võimalik, on soovitatav kasutada Genereerikuid nagu näiteks List või Dictionary. Viimane on eriti kiire kui listist on vaja otsida konkreetseid väärtuseid, kuna tegemist on võti-väärtus paariga. Lisaks saab võtme välja abil välistada duplikaatide esinemist, kuna see peab olema unikaalne. Listi loomisel tuleks anda ette ka selle suurus. Kui seda mitte teha, siis peale seda kui listis saab kohtade arv täis, korrutatakse olemasolev list kahega ja pannakse see Listile uueks pikkuseks. Samuti tuleks sorteeritud listile eelistada List'i, mis sorteeritakse lõpus kasutades ''Sort'' meetodit. Vastasel juhul toimub listi sorteerimine kõik aeg, kus sinna lisatakse uus element. | ||
http://msdn.microsoft.com/en-us/library/ms172181%28v=vs.80%29.aspx + hennu loeng. Samas soovitab üldse massiividele üle minna. | http://msdn.microsoft.com/en-us/library/ms172181%28v=vs.80%29.aspx + hennu loeng. Samas soovitab üldse massiividele üle minna. | ||
==Mäluhaldus== | |||
http://msdn.microsoft.com/en-us/library/ff647790.aspx#scalenetchapt05_topic5 Kui luuakse uus objekt, siis peale new väljakutsumist eraldatakse sellele mälu. Objekti kasutatakse ja ta "sureb" peale seda kui tema väärtus sätitakse nulliks või | http://msdn.microsoft.com/en-us/library/ff647790.aspx#scalenetchapt05_topic5 | ||
Kui luuakse uus objekt, siis peale ''new'' väljakutsumist eraldatakse sellele mälu. Objekti kasutatakse ja ta "sureb" peale seda, kui tema väärtus sätitakse nulliks või enam ei kasutata. See järel vabastatakse objekti poolt kasutatud osa mälust ja seda saavad tarbida teised objektid. Need tuleb luua alati nii hilja kui võimalik, sest nii säästetakse mälu kasutuamist ja nii ei teki ohtu, et see säilib kaua. Peale seda kui objektiga on toimetused tehtud, pole seda enam vaja ning see tuleks "ära visata" ehk väärtus võrtsustada nulliga. Nii teab ''Garbage Collector'', et seda objekti enam ei vajata ning saab selle varakult ära koristada. | |||
Kogu mälu jagatakse neljaks generatsiooniks. Kõik värsked objektid asuvad mälu nullindas generatsioonis. selle täitumisel kutsutakse välja ''Garbage Collector'', mis hakkab seda koristama. Kõik objektid, mis sellele ajal ei osutu prügiks(need, mida veel kasutatake), tõstetakse esimesse generatsiooni, kuna nad on vajalikud. Kui nullindas generatsioonis ei ole midagi kustutada, liigutakse esimesele tasemele. | |||
''Finalizer''ite loomine objektidele on väga ebasoovitatav, kuna nad jäävad prügi koristamise käigus ellu. Nad tõstetakse ''Finalizer qeuesse'' ja nendeni jõutakse alles järgmisel prügikorstamisel. | |||
Eelistatav konstruktsioon on "using", mis hoolitseb selle eest, et selle sees tehtud objekt kustutakse peale selle lõppu. | |||
http://msdn.microsoft.com/en-us/library/ff647790.aspx#scalenetchapt05_topic5 | http://msdn.microsoft.com/en-us/library/ff647790.aspx#scalenetchapt05_topic5 | ||
=Leitud võimaluste rakendamine= | =Leitud võimaluste rakendamine= | ||
Töö praktilises osas tegeleb autor leitud optimeerimisvõimaluste rakendamisega ja tulemuste analüüsimisega. Läbiviidavad muudatused puudutavad eelkõige ERR'i teise põlvkonna .NET portaale news.err.ee ja rus.err.ee | |||
Töö praktilises osas | |||
Testimiseks luuakse virtuaalmasin, mis on antud lahenduste testkeskkonnaks. Serverina kasutatakse Windows Server 2008 R2 Standard ning andmebaasimootoriks on SQL Server 2008 R2 väljannet. Lisaks paigaldatakse ka Visual Studio 2010 Ultimate, millega saab veebirakenduses läbi viia muutusi erinevate testide jaoks. Koormuse simuleerimiseks veebirakendusele kasutatakse ''Apache WampServerit''. Iga koormustest kestab 400 sekundit. Selle käigus jälgitakse, kui palju päringuid suudab server keskmiselt sekundis teeninda ning kui palju võtab aega ühe päringu täitmine. Samuti pööratakse tähelepanu SQL Serveri ja IIS'i protsessori ressursikasutusele testide ajal. Andmebaasiks on kasutusel oleva andmebaasi koopia ja rakendused on testmise alsutamise hetkel ka reaalselt kasutusel. | |||
Põhjalikult uuritakse erinevate optimeerimisvõimaluste kasutamist portaalis rus.err.ee, kuna viimasega on esinenud suurte koormuste korral kõige rohkem jõudlusprobleeme. Esmajärjekorras rakendatakse ASP.Net tehnoloogiast tulenevaid optimeerimisvõimalusi. Võrreldakse milline on mõju jõudlusele väljundpuhvri ja puhvri programmeerimisliidese kasutamise korral ning kumba neist tuleks eelistada. Nende testimiste käigus tehakse andmebaasile päringuid, mida analüüsitakse hiljem. Vaadeldakse neist enimtehtavaid ning analüüsitakse, kuidas saaks neid parandada. | |||
Sellele järgneb eelnevate testide tulemuste analüüs ning vastavalt nendele teostatakse portaali optimeerimine. Tähelepanu pööratakse esilehele ja kategooriavaadele, kuna need on ERR portaalide kõige mahukamad osad ning mitmed neil asuvad komponendid korduvad ka teistel lehtedel. Samuti vaadatakse üle kas .NET enda vahenditest tulenevaid optimeermise võimalused ning vajadusel püütakse neid rakendada. Lähtudes rus.err.ee portaali optimeerimisel tehtud järeldustest, on neid võimalik rakendada ka teistes Eesti Rahvusringhäälingu portaalides, mis kasutavad teise põlvkonna administreerimisliidest. Töö lõpus võrreldakse olemasoleva lahenduse ja töö käigus optimeeritud lahenduste jõudlust. | |||
Antud diplomitöö käigus teostab autor muudatusi kindlasti veebirakenduses, vajadusel ka andmebaasis. | |||
==Esileht ilma optimeerimata== | |||
Kõige esimesena testitakse rakendust ilma väljundpuhvrit ja puhvri programmeerimisliidese kasutamiseta. See tähendab seda, et iga lehe uuesti laadimine põhjustab uued päringud andmebaasi ja terve lehe töötsükli läbimist. Esilehe puhul Tulemused on näidatud allolevas tabelis. | |||
<table border="1"> | |||
<tr><td>Testi pikkus</td> <td>403.2 sekundit</td></tr> | |||
<tr><td>Päringuid lehele</td> <td>72 </td></tr> | |||
<tr><td>Sekundis täidetud päringute arv</td> <td>0.18 </td></tr> | |||
<tr><td>Keskmiselt ühe päringu täitmiseks kulunud aeg</td><td>5,642 sekundit</td></tr> | |||
<table> | |||
Kuna andmeid ei hoita puhvris, siis on nii andmebaasile kui ka veebiserverile pidevalt suur koormus, nagu on näha ka allolevatelt joonistelt. Selle tõttu tekib päringu täitmisel järjekord ning need võtavad kauem aega. Joonisel on näha, et hetkel kui SQL serverile on suur koormus, siis veebirakendusel on see väiksem ja vastupidi. Sellise olukorra ajutise kaotamise jaoks tuleks kasutada väljundpuhvrit või selle programmeerimiseliidest. Järgmises peatükis uuritakse nende mõju jõudlusele täpsemalt.<br /> | |||
IIS:<br /> | |||
[[File:IIS_test_1.jpg]] | |||
<br/> | |||
SQL Server: <br/> | |||
[[File:SQLServer_test_1.jpg]] | |||
<br/> | |||
==Väljundipuhver ja puhverdamisliidese võrdlus== | |||
Lähtuvalt erinevatest optimeerimisvõimalustest, siis võib väita, et kasutades puhvrit on võimalik koormust andmebaasile ja veebiserverile võimalik vähendada, kuna andmeid ei pea pärima ja töötlema enam nii tihti. Nii saab jõudlusprobleemide esinemise korral vähendada neid kasutades puhvrit. Viimast on olemas kahte liiki: puhverdamisliides ja väljundipuhver. Autor viib testib neist mõlemat. Selle eesmärk on selgitada välja kui suur ressursikasutuse vahe esineb nende kasutamisel ning kumba neist peaks eelistama. | |||
Antud lähtetingimused testi läbiviimisel: test kestab 400 sekundit või kuni 50 000 päringu täitmiseni. Testitavaks leheks on rubriigivaade, kus kuvatakse antud kategooria viitekümmet viimast uudist. Selle läbiviimise ajaks eemaldatakse lehelt teised komponendid. Puhvri pikkuseks on mõlema variandi puhul 40 sekundit. | |||
Lähtuvalt peatükist "x.x", kus tuvustati ASP.NET veebirakenduse töötsüklit, peaks olema väljundpuhvri kasutamine kiirem, kuna lehe töötsükli täitmine lõpetatakse juba Algus faasis, kui serveris on leht olemas. Puhverdamisliidese puhul aga kontrollitakse alati, kas puhvris on soovitud andmed olemas ja see järel leiab aset DataBind, kus andmed salvestatakse komponenti. | |||
<table border="1"> | |||
<th></th> <th>Väljundipuhver</th> <th>Puhverdamisliides</th> | |||
<tr><td>Testi pikkus</td> <td>158.18 sekundit</td> <td>402.85 </td></tr> | |||
<tr><td>Päringuid lehele</td> <td>50 000 </td> <td> 45522</td></tr> | |||
<tr><td>Sekundis täidetud päringute arv</td> <td>316.1 </td> <td> 113</td></tr> | |||
<tr><td>Keskmiselt ühe päringu täitmiseks kulunud aeg</td><td>3.1ms sekundit</td> <td>8.8ms </td></tr> | |||
</table> | |||
Antud testi tulemuste põhjal võib järeldada, et võimalusel peaks eelistama alati väljundpuhvri kasutamist, kuna selle kasutamine annab üle kahekordse kiirusevõidu. | |||
==Esileht väljundipuhvris== | |||
Lähtuvalt eelmises peatükis saadud informatsioonist, lisatakse esileht väljundpuhvrisse 40 sekundiks. Võrreldes eelneva testiga, kus puhverdamist ei kasutatud üldse, on tulemuste paranemise arv märgatav. Samas märgib autor, et sellise lahenduse kasutamine pole kindlasti aktsepteeritav. Nagu graafikutelt on näha, siis puhvri tühjaks saamisel andmete uuesti pärimine toob endaga kaasa nii veebi- kui andmebaasiserveris väga järsu ressursikasutuse kasvu. Arvestades asjaolu, et ERRis on ühel serveril veel mitu teist portaali, tuleks sellist situatsiooni vältida, kuna erinevate portaalide puhvrid võivad tühjaks saada samal ajal. See põhjustab kordades suurema koormuse, kui ühe portaali puhul. Võimalikult hea tulemuse saamiseks tuleks kasutada osalist väljundpuhvrisse lisamist, kus komponentidele antakse ette erinev aegumisaeg. See peaks tagama autori arvates lehele ühtalsema koormuse jaotamise. Seetõttu ei ole soovitatav kasutada ka ''SQLCacheDependencyt'' komponentides, mille uuendus sõltub sama andmetabeli muudatustest. Muidu tekib sarnane situatsioon nagu antud testis:Hetkel kui jälgitavas tabelis toimub muutus, tühjenevad kõik puhvrid kõikidel komponentidel, mis seda kasutavad. Antud organisatsiooni puhul on see eriti aktuaalne, kuna samu andmebaasitabeleid kasutavad 8 erinevat portaali. | |||
Samuti ei saa kasutada väljundpuhvrit kohtades, kus toimub lehele tagasipostitus või toimub andmete täitmine näiteks ruutingu tingimusest lähtuvalt, sest lehe töötsükkel lõpetatakse juba algusfaasis, mis välistab edasise andmete töötlemise. Viimased komponendid on Eesti Rahvusringhäälingu portaalides näiteks kommenteerimisvormid, küsitlus ning "Samal teemal" kast. | |||
<table border="1"> | |||
<tr><td>Testi pikkus</td> <td>301.62 sekundit</td></tr> | |||
<tr><td>Päringuid lehele</td> <td>50 000 </td></tr> | |||
<tr><td>Sekundis täidetud päringute arv</td> <td>165,77 </td></tr> | |||
<tr><td>Keskmiselt ühe päringu täitmiseks kulunud aeg</td><td>0.6 sekundit</td></tr> | |||
<table> | |||
IIS:<br/> | |||
[[File:IIS_test2.png]] | |||
<br/> | |||
SQL Server: <br/> | |||
[[File:Sqlserver_test2.png]] | |||
==Andmete sidumine== | |||
Nagu autor ka eelpool välja tõi, ei saa kasutada väljundipuhverdamist Eesti Rahvusringhäälingu portaalis mitmel komponendil. Üheks selliseks on ka kategooriavaade, mille sisu täidetakse vastavalt ruutingu esimes kohal asuvale väärtusele. See ütleb, millise rubriigiga on hetkel tegu. Selleks, et neid andmeid mälus hoida, tuleks kasutatada puhverdamisliidest, kuhu lisatakse andmetabel, milles kuvatavad väljad asuvad. | |||
Väljakuvamiseks kasutatakse hetkel listivaadet ja Eval operaatorit. Peatükkide 4.3 ja 4.4 põhjal väita, et hetkel on tegemist on ebaoptimaalse ressursikasutusega. Listivaade genereerib lehele ohtralt viewstate'i ja selle funktsionaalsust antud lahenduse puhul tegelikult vaja ei lähe. ''Eval'' operaatori kasutamine on samuti kulukas lähtudes leitud materjalidest. | |||
See tõttu asendatakse listivaade kordajaga ''(repeater)'' ning ''Eval("väljanimi")'' operaatori asemel kasutatakse ((System.((System.Data.DataRowView)Container.DataItem)["väljanimi"] varianti. Kasutatakse 40 sekundilist puhverdamist. | |||
<table border="1"> | |||
<th></th> <th>Uus versioon</th> <th>Vana versioon</th> | |||
<tr><td>Testi pikkus</td> <td>394.229 sekundit</td> <td>402.85 </td></tr> | |||
<tr><td>Päringuid kokku</td> <td>50 000 </td> <td> 45522</td></tr> | |||
<tr><td>Sekundis täidetud päringute arv</td> <td>126.83 </td> <td> 113</td></tr> | |||
<tr><td>Keskmiselt ühe päringu täitmiseks kulunud aeg</td><td>7.885msms sekundit</td> <td>8.8ms </td></tr> | |||
</table> | |||
Lähtudes mõõtmistulemustest tuleb tõdeda, et optimaalsem on kasutada materjalidest leitud võimalusi ning neid tuleks rakendada ka mujal. | |||
==Andmebaasipäringute optimeerimine== | |||
Peale andmebaasipäringute analüüsimist selgus, et praeguse lahenduse korral pole kohati indekseerimisest eriti kasu. Tehtavad päringud võtavad tihti rohkem infot kaasa kui vaja, kuna valitakse kõik veerud. Samuti tehakse kõiki neid päringuid rakenduses ning mitmes osas. Otsitakse üles uudised, nende kategooriad, siis tekst ja nii edasi. Anmdebaasiühendusi avatakse ja suletakse tihti, mis on aega võttev protsess. Autor leiab, et arvestades antud situatsiooni, tuleks luua andmebaasi protseduur, mis tagataks soovitud väärtused. Nii on päringuid lihtsam hallata. Loodav lahendus peaks olema piisavalt paindlik, et seda saaks kasutada ka teistes portaalides. | |||
==Läbiviidavad muudatused== | |||
Antud veebirakenduse jõudluse parandamiseks luuakse protseduur, mis oleks võimalikult paindlik, et seda saaks kasutada ka teistes portaalides. Peale selle valmimist tuleb olemasoleva lahenduse koodis viia läbi muudatusi. Hetkel on veatöötlemine lahendatu try catch plokkidega kohtades, kus seda tegelikult vaja ei lähe. Erinevad päringud andmebaasi poolele asendatakse loodava protseduuriga, mis suudab anda tagasi kogu info. Selle arvelt peaks kasvama andmebaasist saadavate päringutele vastuste saamine. Puhverdamisel eelistatakse võimalusel väljundpuhvri kasutamist, kuna see on võrreldes puhverdamisliidesega kiirem ja põhjustab veebiserverile vähem koormust. Nagu joonistel näha oli siis hetkel kui puhvrit hakati uuesti täima, tekkis sellel ajal nii veebiserverile kui ka andmebaasile järsult suur koormus. Kuna Eesti Rahvusringhäälingu puhul on ühes serveris mitu erinevat portaali tuleks sellist olukorda vältida. Selleks pannakse puhvri aegumise ajad erinevad, et jagada koormust ühtlasemalt. | |||
=Venekeelsete uudiste portaal= |
Latest revision as of 16:14, 4 May 2011
Siin lehel kirjutan oma diplomitööd. Alustan 19.märtsil probleemi kirjeldusega.
Olemasoleva olukorra ja probleemi kirjeldus
Selle peatüki eesmärk on anda lühike ülevaade Eesti Rahvusringhäälingust ja selle portaalidest ning olemasolevast lahendusest.
Eesti Rahvusringhääling
Ilus organisatsiooni skeem
Eesti Rahvusringhäälingu moodustavad kaks tele- ja viis raadioprogrammi, millele lisanduvad juurde veel mitmed uudiste- ja teemaportaalid. Organisatsioon hakkas sellisel kujul tegutsema 1. juunil 2007, kui ühendati Eesti Raadio ja Eesti Televisioon. Viimast esindavad ETV ja ETV2 ning raadiod Vikerraadio, Klassikaraadio, Raadio 2, Raadio 4 ja Raadio Tallinn.
Rahvusringhäälingu kõige olulisem tegevus on sisu tootmine.
Missiooniks on arendada ja hoida Eestit ning selleks kaasatakse inimesi Eesti riigi ellu, innustatakse vaba arutelu, edendatakse loomingulisust ja tegusust. Luuakse teabevõrgustik kõigi Eestiga seotud inimeste vahel kogu maailmas, oma programmides avardatakse Eesti inimeste maailmapilti, haritakse avalikus mõtteruumis osalejaid, väärustatakse inimeste isiklikku elu ja perekonda, kaitstakse eetilisi põhiväärtusi.
Raadio-ja teleprogrammide kõrval mängivad olulist rolli missiooni täitmisel ka Eesti Rahvusringhäälingu internetiportaalid. Näiteks on antud organisatsioon loonud ainsana inglise keelse portaali, mis kajastab Eestit. Samuti tehakse seda ka vene keeles. TNS-i Emor andmetel oli Rahvusringhäälingu portaalide lugejaskond 2010. aasta lõpul enam kui 165 tuhat lugejat nädalas. Eesmärk on olla viie esimese ajakirjanduslikku sisu pakkuva portaali seas.
Samuti on loodud võimalused jälgimaks kõiki tele- ja raadioprogramme otsesaateid üle maailma läbi interneti, et olla Eestis toimuvaga kursis. Praegu tegeletakse sellega, et tuua otsetoodang ka mobiili ja inimesed saaksid programme jälgida sõltumata seadmetest. Internetis saavad oluliseks ka ineteraktiivsed keskkonnad ja sotsiaalvõrgustikud.
Portaalide arendus ERR'is
ERR'is tegeleb portaalide arendusega portaalide arenduse üksus. Ametikult loodi see 1. jaanuar 2011. Praeguse hetkel kuuluvad meeskonda ametlikult 4 arendajat ja veebiarendusjuht. Eelnevalt vastutas arenduse eest üks isik. Kõik uued portaalid luuakse hetkel ASP.NET 4 platvormil, millega paralleelselt toimub vanema ASP.NET generatsiooni portaalide üle toomine uuemale versioonile. Lisaks .NET raamistikku kasutavatele portaalidele on hetkel veel ka PHP lahendusi, millele ei tehta enam väga suuri juurdearendusi.
PHP tehnoloogial portaalid Eesti Rahvusringhäälingus
Alljärgnevas peatükis tutvustatakse erinevaid PHP portaale Eesti Rahvusringhäälingus.
PHP4 tehnoloogial arendatud portaalid
PHP 4 portaalidest on kõige pikema ajalooga etv, mis loodi PHP4 tehnoloogial aastal 2003. Eksisteeris ka varem, kuid selle ajalugu on hetkel teadmata. Sellele järgnes uudisteportaal 2006ndal aastal, mis esialgu kandis nimetust etv24. Ilm loodi aastal 2009.
- etv.err.ee - ETV kanali portaal, võimalik jälgida tagantjärele saateid ja nende uudiseid.
- uudised.err.ee - uudiste portaal.
- ilm.err.ee - ilma portaal.
- meieoma.ee - lastele mõeldud portaal.
PHP5 tehnoloogial arendatud portaalid
PHP5 portaalidest on kõige pikema ajalooga raadioportaalid. Alates 1995ndast aastast kuni aastani 2000 toimus nende haldamine kasutades staatilist HTML'i. Peale seda võeti kasutusele PHP3 ja aastal 2002 PHP4. 2007ndal aastal valmisid kõik raadioveebid baseerudes PHP5'le, neist viimane portaal - klassikaraadio, valmis sama aasta detsembris.
Kõige uuemad lahendused on pood.err.ee ja teadus, mis valmisid 2010. aasta septembris.
- pood.err.ee - võimalik osta ERR toodangut.
- Raadioportaalides on võimalik lugeda nendega seonduvaid uudisedeid, kuulata saateid arhiivist ja ka otse.
- vikerraadio.err.ee
- r2.err.ee
- r4.err.ee
- raadiotallinn.err.ee
- klassikaraadio.err.ee
- teadus.err.ee - teadus- ja haridussaadete portaal.
- raadioteater.err.ee - võimaldab kuulata vikerraadios esitatud kuuldemänge ja järjejutte.
ASP.NET platvormil portaalide arendus Eesti Rahvusringhäälingus
Miks? Kes?Kus? Kuidas?
2009 aastal lisandus ERR portaalidesse Arendusjuht. Tema ülesandeks oli analüüsida tehnoloogiate ja rakenduste hetkeseisu ning võimalikke lahendusi. Peale esimest poolaastat analüüse langetati otsus kasutada ühtset valmis võimekat veebimootorit ning osta sisse esmane arendus, kuna organisatsioonis puudus vajalik tööjõud. Selle tegevuse tulemusena alustati taotlust Riigihankele läbi Euroopa Struktuurifondide. Tehnoloogiliseks alusstandardiks sai Microsft.NET platvorm tänu vahendite võimekusele ja tööjõudlusele. Kuna hanked on pikk protsess siis alustati esimeste portaalide üleviimist ning uute rakenduste loomist. Kõige esimeseks rakenduseks sai keskportaal (err.ee) ning see hostiti Microlingi avalikus hostingus kuna .net platvormi infrastruktruu on üks osa riigihankest. Alates aastast 2010 omab organisatsioon minimaalset infrastruktuuri .net platvormi teenindamiseks siseselt ning aastal 2011 tarniti riigihanke raames hangitud riist ja tarkvarile platvorm mille lõplik avalik käivitamine toimub kevadel 2012.
ASP.NET 2.0
- err.ee -Eesti Rahvusringhäälingu keskportaal.
- om.err.ee - Taliolümpiamänge kajastav portaal.
ASP.NET 4.0
- news.err.ee - Eestit kajastav ingliskeelne uudiste portaal
- eestilaul.err.ee - Eesti Laulu ja Eurovisiooni kajastav teemaportaaal
- otse.err.ee - Portaal, mis võimaldab jälgida ERR'i tele-ja raadiotoodangut reaalajas.
- valijakompass.err.ee - teemaportaal mis aitas võrrelda inimestel enda seisukohti erakondade omadega.
- koolifilm.err.ee - koolifilmi konkurssi läbiviimiseks loodud portaal
- rus.err.ee - Eestit kajastav venekeelne uudisteportaal.
- retseptid.err.ee - portaal, kuhu lisatakse eetris olnud retsepte.
- kodanik.err.ee -
- jalgpall.err.ee - Portaal, mis kajastas jalgpalli MM 2010't
- ring.err.ee - ERR portaalide registreeritud kasutajate..
- etv2.err.ee - kajastab ETV2'ga seotud uudiseid/üritusi.
Probleemi kirjeldus
Teise põlvkonna ASP.NET portaalide jaoks loodud lahendus valmis kiirustades, kuna selle valmistamine toimus äärmiselt piiratud ajaraamis ja tööjõudu selle projekti tarvis oli vähe. Seetõttu puudus oodatava süsteemi põhjalik eelanalüüs. Rakenduse loomiseks kasutati töövõtteid, mis kiirendasid küll selle valmimise kiirust, kuid paratamatult kannatas selle all rakenduse kvaliteet (sh jõudlus). Ametlikku kasutuselevõttu eel ei olnud võimalik, tulevenalt ajaraamist, teha süsteemile täielikke jõudlusteste, mis näidanuks selle toimimist suurte koormuste korral. Teise põlvkonna ASP.NET portaalide mootori valmimise hetkel hakati seda lahendust kasutama vaid ühe portaali piires. Hiljem lisandus sellele platvormile täiendavaid portaale ning jõudluse küsimus muutus seepärast aktuaalseks.
Arendusmeeskonda on lisandunud noori programeerijaid, kes ei ole piisavalt teadlikud kuidas tagada korraliku koodikvaliteeti. ASP.NET lahendusi on küll võimalik pealtnäha kiiresti ja kergelt luusa, kuid kasutades valesid tehnoloogiaid ning töövõtteid ja jättes optimaalse ressursikasutuse jälgimise tagataustale, mõjub see rakenduse jõudlusele negatiivselt.
Poole aasta jooksul on lisandunud uusi .NET portaale, milledest enamus kasutab eelpool mainitud lahendust. Viimasel ajal on esinenud suurte koormuste korral märgatavaid jõudlusprobleeme. Üheks põhjuseks on kindlasti asjaolu, et kõiki .NET portaalide haldamiseks on kasutada ainult üks server. Ehk kui üks portaal hakkab kasutama väga palju ressurssi, siis mõjutab see ka teiste veebirakenduste tööd. See on kindlasti hetkel ka üheks turvanõrkuseks - leides ühel leheküljel ressursinõudliku protseduuri, saab seda kasutada kõikide Eesti Rahvusringhäälingu ASP.NET portaalide töö häirimiseks. Halvimal juhul lõpeb see serveri töö seiskumisega. Serveripargi jõudluse parandamiseks on täiendavad investeeringud riistvarasse hetkel välistatud. Kuna organisatsioon tegutseb internetimeedia turul ja laieneb sellel pidevalt, siis häired veebirakenduste töös mõjuvad mainele negatiivselt ning on oht kaotada külastajaid.
Lähiajal on lisandumas antud serverile veel kaks täiesti uut portaali. Lisaks peavad hakkama mõned esimese põlvkonna portaalid kasutama "uut mootorit", üheks neist on sport, millele on oodata suurt külastajatearvu. Arvestades asjaolu, et juba praegu esineb jõudlusprobleeme, tuleb enne parandada olemasoleva lahenduse jõudlust.
Antud peatükis andis autor ülevaate konkreetse organisatsiooni probleemi tekkimise põhjustest, lisaks käsitleb peatükis 2.3 "Optimeerimisest üldiselt" jõudlusprobleemide esinemist laiemalt.
See osa on selgelt liiga lühike
Võimalik viide, et probleemi aktuaalsust üldisena käsitleb autor peeatükis see ja see
Metoodika valik ja võimalikud lahendused
Selles peatükis selgitab autor töös kasutatavat metoodikat ning annab ülevaate käsitletava teema valdkonnast üldiselt.
Metoodika
Lahenduse leidmiseks teostab autor teoreetilise uuring kasutatakse olemasolevate materjalide analüüsi ning seejärel koostab olemasolevate rakenduste optimeerimise kava. Lõputöö käigus tutvutakse parimate praktikatega ja valitakse välja neist sobivaimad. Valiku tegemisel hinnatakse sobivust olemasoleva lahendusega. Kui valik on teostatud mõõdetakse praeguse lahenduse töökiirust. Peale seda võetakse kasutusele leitud optimeerimisvõimalused, mida rakendatakse kõigepealt testserveris, millele järgnevad uuesti mõõtmiseid. Võrreldakse saadud tulemusi ja tehakse järeldus.
ASP.NET veebirakenduse põhikomponendid ja töötsükkel
http://msdn.microsoft.com/en-us/library/ms178472.aspx
Tänapäeval kasutab enamus veebirakendusi dünaamilist sisu kuvamist, kuna see teeb lehtede haldamise mugavamaks ja paindlikumaks. Enamasti hoitakse sisu andmetena andmebaasis, mida päritakse sealt, korrastatakse ja kuvatakse see järel kasutajatele. Selle kuvamise lihtsustamiseks on ASP.NET raamistikul mitmeid komponente nagu näiteks ListView, GridView ja ka teisi listidel baseeruvad komponente.
Nende kasutamiseks peab teadma kuidas töötab lehe elutsükkel ja kuidas toimub andmeseondamine (Data Binding)
Komponendi andmeseondamise sündmus leiab aset pärast komponendi PreRender sündmust, mis leiab omakorda aset pärast lehe PreRender sündmust. See märgib protsessi algust, mile käigus hakatakse komponenti andmetega siduam. Seda meetodit saab kasutada manuaalseks andmebaasiühenduse avamiseks.
RowCreated(GridView) või ItemCreated sündmus (teisteö listidel baseeruvat komponentide puhul) täidetakse pärast andmesidumist. Seda saab kasutada manipuleerimiaks sisuga , mida kuvatakse.
RowDataBound(GridView) või ItemDataBound(teistel listidel baseeruvate komponentide puhul) sündmuse käigus on rea või kirje puhul. Võimalik seda vormindada või kuvada sellega seotud andmeid konkreetse rea või kirjega.
DataBound sündmus kutsutakse andmetesidumise lõppedes.....34h ilma magamata...
Etapp | Kirjeldus |
---|---|
Lehe pärimine (Page request) |
Leiab aset pärast lehe töötsükli algust. Kui seda päritakse, siis ASP.Net teeb kindlaks, kas lehte on vaja parsida ja kompileerida või on puhvris antud lehe versioon juba olemas. Viimase variandi puhul saab selle resveerida ilma töötsüklit jätkamata. |
Algus(Start) |
Algusfaasis väärtustatakse lehe atribuudid nagu näiteks Request ja Response. Samuti otsustatakse, kas tegemist on tagasipostitusega või uue päringuga. Ükski komponent pole veel kättesaadav. |
Intsialieerimine(Initialization) |
Selle protsessi käigus loodakse komponendid ja lisatakse lehe komponentide kollektsiooni. Igale ühele neist luuakse unikaalne tunnusUniqueID. See on ainus töötsükli osa kus nägusid või pealhti saab dünaamiliselt muuta. ViewState pole veel taastatud. |
Laadimine(Load) |
Kui antud protsessi käigus ilmneb, et tegemist on tagasipostitamise, siis laetakse komponentide atribuudid view state' ja control stateist. Selles osas tuleb enamasti küsida andmebaasist andmeid. |
Tagasipostituse sündmuse töötlemine(Postback event handling) |
Kui tegemist on tagasipostitusega, siis kutsutakse välja kontrollide sündmusetöötlejad (event handler). Peale seda kutsutakse välja Valid meetod mis paneb paika IsValid atribuudi kõikidel kontrollidel ja lehele |
Renderdamine(Rendering) |
Siin toimub toimub viewstate'i salvestamine lehe ja kõikide komponentide jaoks. Selle protsessi käigus kutsub leht iga kontrolli jaoks välja Render meetodi, mis kirjutab lehe ja iga komponendi HTML'i ja saadab selle väljundisse. |
Unload |
Meetod kutsutakse esile, kui leht on täielikult renderdatud ja kliendile saadetud. Sel juhu vabanetakse atribuutidest nagu näiteks Response ja Request ning toimub koristus. |
Optimeerimisest üldiselt
Tänapäeval on jõudlusprobleemid väga aktuaalsed, kuna IT-lahendused ning nende funktsionaalsute maht kasvab ajas kiiresti ning populaarsete veebirakenduste kasutajate hulk võib ajas eksponentaalselt kasvada. Kui veebirakendused on optimeerimata, siis võib kasutajate hulga lisandumine põhjustada halvimal juhul rakenduse töö katkemise või mitteootuspärase kasutajakogemuse.
Tihti häirivad optimeerimata veebirakenduste tööd jõudlusprobleemid. Viimased kerkivad esile, kui süsteemile kasvab koormus ning tihti on nende tekkimist raske prognoosida. Olukorra iseloomustamiseks võib näite tuua liikluses: kell 4 öösel tööle sõit võtab alati vähem aega, kui seda teha hommikusel tipptunnil, teisalt võib juhtuda, et hommikul kell seitse toimub mõni oluline tähtsündmus ning öösel kell 4 on ootamatult tekkinud ummikud, kuna valgusfoorid ei tööta, aga liikluskoormus on suur. Nii võib juhtuda, et veebirakeendusel, kus tavapäraselt on paartuhat külastajat päevas, kasvab ühel päeval kasutajate hulk kümnetes kordades, kuna rakendusele tegi reklaami mõni meeldiakanal või populaarne sotsiaalmeedia kasutaja.
Sellised näited on EERi kogemuses näiteks otse.err.ee portaalis, kus mõne aktuaalse sündmuse ajal võib kasvada kasutajate hulk järsult kümnetes kordades. Varasemalt on seda juhtunud eurovisiooni ja spordiülekannete puhul, mille tulemusena käitus leht mitteootuspäraselt.
Parem kirjuta vormis: selle vältimiseks saab kasutada...
Sellise olukorra vältimiseks on alati kõige lihtsam juurde soetada riistvara, mis annab omakorda juurde rohkem jõudlust. See on õigustatud ainult juhul, kui on kindlaks tehtud, et süsteem on juba optimeeritud ja olemasolevate vahenditega pole seda enam võimalik parandada. Vastasel juhul on tegemist probleemi ajutise peitmisega, mitte lahendamisega. Lisaks kulutatakse nii ebaotstarbekalt rahalisi vahendeid. Seega tuleks alati alustada probleemi lahendamist olemasoleva lahenduse analüüsiga ja võimaluse korral optimeerimisega.
Süsteemi tuleb alati vaadata kui tervikut. Näiteks veebileht ei koosne ainult koodist, mis kirjutab välja vajalikke asju. Seda infot tuleb käia kuskilt pärimas - andmebaasist. Lehe reserveerimise eest vastutab aga server. Ükskõik millise eelpool mainitud osa halvasti töötamine mõjutab teisi. Parandades ühte osa, paraneb enamasti ka üldine jõudlus, kuid maksimaalse kasutegerui saavutamiseks tuleb vaadata rakenduse kõiki osasid. Edukalt probleemide lahendamisel võib nii vältida täiendava riistvara soetamist ja tagada parema süsteemi töökindluse.
Enne optimeerimise alustamist tuleks veenduda, et plaanitav muudatus on vajalik ning see toob kaasa endaga jõudlusekasvu. Näiteks, kui kulutada kaks päeva andmebaasipäringu optimeerimiseks, mida tehakse kord aastas ja sellega võidetakse paar millisekundit, siis tegelikkuses on kaotatud 2 väärtuslikku tundi. Lisaks tasub jälgida, milliseid muudatusi toob tehtva muudatus kaasa olemasolevas lahenduses, kuna muutus, mis muudab koodi loetamatuks ja selle silumise raskeks ei pruugi olla alati õigustatud.
Antud lõputöö raames vaatleeb autor eelkõige enimkasutatavaid ja suuremat jõudlusvõitu tagavaid võtteid ASP.NET veebirakenduse optimeerimiseks ning seda, kuidas neid olemasolevates ja ka uutes ERRi portaalimootorites rakendada. Tuuakse välja ka võimalused, kuidas mõõta erinevate rakenduse osade töötamiskiirust, millele tuleks selle juures tähelepanu pöörata ja milliseid muudatusi see endaga kaasa toob. Lisaks luuakse dokument, mida saab kasutada uute loodavate lahenduste varajaseks optimeerimiseks tulevikuks. Eeludseks on, et tegemist on .NET 4 raamistikuga ja andmebaasina kasutatakse SQL Server 2008 väljaannet, kuna need on antud töö aluseks.
Andmebaasi optimeerimine
Siia pigem jutt, miks on andmebaaside optimeerimine rakenduse optimeerimise seisukohast oluline
Mõiste "Andmebaas" defineerib wikipedia järgnevalt:"Andmebaas on korrastatud infokogum." http://et.wikipedia.org/wiki/Andmebaas Sellest vajaliku osa näitamise eest lõppkasutajale vastutab enamasti rakendus, mis pärib seda andmebaasist. Järelikult võib väita, et sellise rakenduse töö sõltub lisaks muule ka andmebaasist. See tõttu on viimase kiire ja optimaalne töötamine prioriteetne, kuna aeglane andmete leidmine ei mõjuta ainult andmebaasi enda tööd, vaid ka rakendust. Kui andmebaasi päringute täitmine võtab palju aega, peab rakendus ootama vajalike andmete järel, enne kui saab oma tööd jätkata.
Antud peatüki eesmärgiks on kirjeldada võimalusi andmebaasi optimaalse töö tagamiseks. Lisaks peab autor vajalikuks kirjutada ka selle loomisest, kuna materjalide analüüsist selgus, et andmebaasi jõudluse tagamisel mängib väga suurt rolli ka selle disain. Halva arhitektuuriga andmebaaasi on väga keeruline optimeerida.
Microsoft SQL Server 2008 andmebaasimootori väljaanded ja nende funktsionaalsuste erinevus
Microsoft SQL Server 2008 on 6 erinevat väljaannet: Express, Workgroup, Web. Standard, Enterprise ja Datacenter. Antud nimekirja järjestus baseerub litsentside hinnal, milles kõige esimene on Express versioon. See on tasuta ja kõige väiksema funktsionaalsuse ning võimalustega. Töö käigus kasutas diplomitöö autor Standard väljaannet. Selle peatüki eesmärgiks on lühidalt võrrelda ja kirjeldada erinevate väljaannete funktsionaalsust lähtuvalt jõudlusest.
Tabelite ja indeksite partitsioneerimine (Table and index partitioning) - võimaldab tabelid ja indeksid jagada väiksemateks osadeks. See on kasulik suure hulga andmete puhul, sest sellest väiksema osa läbi vaatamine võtab vähem aega ja ressurssi. SQL Server 2008 Bible 1428
Indekseeritud vaated (Indexed views) - Tavalised vaated on virtuaalsed tabelid, mis luuakse alati iga päringu ajal uuesti. Indekseeritud vaadete puhul aga hoitakse selle päringu tulemusi andmebaasis tabelina. Lisaks sellel suudab päringuoptimeerija(query optimizer) vajadusel loodud vaadet kasutada päringute täitmiseks ilma, et seda peaks FROM klauslis eraldi kirjeldama.
http://msdn.microsoft.com/en-us/library/ms187864.aspx
Andmete tihendamine(Data Compression)- võimaldab tihendada tervet kuhja(heap), klasterdatud indeksit, klasterdamata indeksit, indekseeritud vaadet ja üksikut tabelit või indeksi partitsiooni. Näiteks mahub seetõttu lehtedele rohkem ridu ja kirjete läbi vaatamine toimub kiiremini. Peab arvestama, et kõik andmed ei kompresseeru hästi ja lisaks mõjutab see protsessori jõudlust. (SQL Server 2008 Bibile lk 1416)
Ressursi haldur (Resource governor) - tööriist, mille abil saab määrata erinevatele päringutele ressursipiirangud ja limiidid. Kasulik olukorras, kus suur ja väikeseprioriteediga päring, kasutab palju ressurssi. Viimasele saab määrata maksimaalse protsessori kasutuse piiri. Nii võtab selle päringu täitmine küll rohkem aega, kuid kasutab vähem ressurse. http://msdn.microsoft.com/en-us/library/bb895232.aspx
Parallel index operations - vähendab aega, mis kulub indeksite loomiseks ja ülesehitamiseks kasutades mitme protsessori tuge. http://msdn.microsoft.com/en-us/library/ms191292.aspx
Parallel consistency checks (DBCC) - võimaldab andmebaasi käsurea päringuid täita paralleelselt ja seega kiiremini.
Enhanced read-ahead scan - ei saa aru. http://msdn.microsoft.com/en-us/library/ms191475.aspx
- | Express | Workgroup | Web | Standard | Enterprise | Datacenter |
---|---|---|---|---|---|---|
Protsessorite arv | 1 | 2 | 4 | 4 | 8 | Operatsioon süsteemi maksimum |
Maksimaalne mälukasutus | 1GB | 4GB | 64GB | 64GB | 2TB | Operatsioon süsteemi maksimum |
Maksimaalne andmebaasi suurus | 10GB | 524PB | 524PB | 524PBB | 524PB | 524PB |
Tabelite ja indeksite partitsioneerimine | Ei | Ei | Ei | Ei | Jah | Jah |
Indekseeritud vaated | Ei | Ei | Ei | Ei | Jah | Jah |
Andmete tihendamine | Ei | Ei | Ei | Ei | Jah | Jah |
Ressursi haldur | Ei | Ei | Ei | Ei | Jah | Jah |
Parallel index operations | Ei | Ei | Ei | Ei | Jah | Jah |
Parallel consistency checks (DBCC) | Ei | Ei | Ei | Ei | Jah | Jah |
Enhanced read-ahead scan | Ei | Ei | Ei | Ei | Jah | Jah |
Andmebaasi loomine
Andmete hoiustamiseks andmebaasis, tuleb see enne luua. Selle protsessi käigus tehtud otsused mõjutavad väga palju tulevikus jõudlust ja ressursikasutust. Algfaasis tehtud valed valikud mõjuvad halvasti nii andmebaasi kui seda kasutavale rakenduse kiirusele. Oluline on andmebaasi loogiline ülesehitus, kuid tähelepanu tuleb pöörata ka kindlasti veergude definitsioonidile, mis tuleb määrata korrektselt ja loogiliselt. Näiteks reaalarvulised väärtused peavad olema reaalarvu tüüpi, tekstina neid hoides raisatakse ressurssi ning andmete lugemisel peab neid üldjuhul kasutamiseks teisendama vajalikku vormingusse. Samuti tuleb veerutüüpide loomisel alati läbi mõelda, kui täpseid andmeid nõutakse. Lihtne näide selle kohta on kuupäevad, mida kasutatakse alati väga palju. Näiteks registreerimaks uue sissekande loomise kuupäeva. Tihti kasutatakse andmebaasis kuupäeva tüübiks automaatselt DateTime, mis võtab ruumi 8 baiti ja täpsuseks kolm millisekundit. Kuid enamasti ei ole selline täpsus vajalik ning väiksema täpsusega andmete hoiustamiseks ja töötlemiseks kulub vähem ressursse. Samas on olukordi, kus väärtuste suur täpsus on kriitiline, kuid kindlasti leidub rohkem situatsioone, kus piisab ka väiksemast täpsusest.
Näiteks uudisteportaalides on uudiste avaldamisajad tihti märgitud ainult kuupäeva koos kellaajaga, mis on minutitäpsusega. Viimase jaoks on sobiv SmallDateTime, mis on minuti täpsusega ja lisaks võtab poole vähem ruumi (4baiti). Lisaks on sellisel juhul olemas vajalikus vormingus kuupäev ning seda ei pea hakkama veebirakenduses andmete väljaküsimusel ümber hakkama vormindama.
Andmebaasi loomisel tuleb säilitada paindlikus. Näiteks tabelis võtab tinyint primaarvõtme väljana 4 korda vähem ruumi võrreldes Int tüüpi veeruga, kuid sellesse tabelisse saab luua see tõttu ka 256 sissekannet.
Samasuguseid näiteid leidub kõigi andmetüüpide kohta. Seega peaks enne tabelite loomist ja veergude tüübi määramist tutvuda konkreetse andmebaasimootori dokumentatsiooniga ja analüüsida, milliseid võimalusi võimalused on olemas. Näitena võib tuua eelpool mainitud kuupäevade tüübi valimise, kuna SmallDateTime on saadaval alates SQL Server 2008 versioonist.
Kordumatute väärtustega väljad andmebaasides
Andmebaasi loomisel tuleb otsustada, millist tüüpi on primaarvõtme veerud. Tihti on nendeks INT või uniqueidentifier. Esimene neist esindab täisarvulisi arve ja teise puhul on tegemist kordumatute väärtustega, mis on 16 baidised globaalsed identifikaatorid (GUID- Global Unique IDentifier). Need esitatakse kujul xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, kus iga x tähistab üht tähte või arvu kuueteistkümnendsüsteemist.
Siia selgitus, milleks sellised väljad andmebaasides üldse kasutusel on ning mis on INT ja mis GUID
Arvestades kui palju kordumatu väärtusega identifikaator ruumi võtab, võrreldes täisarvuga, võib selle kasutamine tunduda ebaratsionaalne. Siiski on sellel täisarvu ees ka mõned eelised.Näiteks on see alati unikaalne, kuid täisarv on unikaalne ainult ühes tabelis. Samuti on selle kasutamisega välistatud võimalus, et relatsioonilises andmebaasis viiakse omavahel kokku tabelite veerud, mis tegelikult ei ole seotud. Lisaks ei saa GUID kunagi otsa, kuid täisarvulise tüübi kõige suurem väärtus on 9 223 372 036 854 775 807, kui tegemist on bigint 'iga ja sellel juhul võtab see ruumi 8 baiti. [1]
Üheks kordumatu väärtusega välja puuduseks on see, et selle kasutamine võib vähendada klasterdatud indeksiga saavutatud jõudlusevõitu, kui selle genereerimine toimub väljaspool andmebaasi. Iga uus sissekanne nõuab indeksite uuendamist ja seetõttu võib selle kasutamine kutsuda esile indeksi lehtede poolitusprobleeme ja nende fragmenteerumist, kuna loodud võtme väärtus ei pruugi olla viimane ja sellele tuleb leida õige koht. See nõuab aga kõigi seniste võtmete uuesti sorteerimist. Alates SQL Server 2005 versioonist saab selle vältimiseks kasutada funktsiooni NewsequentialID(), mis tagab, et iga järgmine globaalne identifikaator on eelmisest suurem. Seega ei tule uus sissekanne mitte indeksite lehe keskele, vaid läheb alati viimaseks. Tuleb arvestada ka asjaoluga, et kuna see kasutab rohkem mälu, siis tekib indekseerimisel rohkem lehti ja nende uuendamine on kulukam kui täisarvulise tüübi puhul.
Päringute analüüs
Kirjete lisandumisel andmebaasi kasvab selle suurus ja ka päringute täitmiseks hakkab kuluma rohkem aega. Mingil ajahetkel võib tekkida situatsioon, kui andmete leidmiseks kulub liiga palju aega. See on aga selge märk sellest, et tehtavaid päringuid tuleks analüüsida ja seejärel optimeerida.
Alljärgnev päring aitab otsustada, millised päringuid andmebaasis võivad vajada optimeerimist.
-- alljärgneva päringuga saad lugeda protseduur cache'i sisu
-- saadav tabel sisaldab küllalt infot otsustamaks, millised protseduurid või päringud kulutavad serverit
SELECT sql.text, qs.EXECUTION_COUNT, qs.*, p.*
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(sql_handle) sql
CROSS APPLY sys.dm_exec_query_plan(plan_handle) p
WHERE text NOT LIKE '%sql.text%'
ORDER BY
-- vali ise mis järjekorras sa vastust tahad
--qs.total_worker_time desc -- kulutatud aja järgi
qs.EXECUTION_COUNT DESC -- täitmiskordade järgi
--qs.max_elapsed_time DESC -- maksimaalse kestuse järgi
--vajaduse saad protseduur cache'i puhastada
--CHECKPOINT --writes dirty pages to disk
--DBCC FREEPROCCACHE --clears entire plan cache
--NB! Viimases veerus saadud tabelis on XML kujul Query Plan
--Salvesta see laiendiga sqlplan ja ava Management Studios - ja imesta :)
(http://www.sarv.ee/ftp/henn/SQL/Proc%20cache%20statistika.sql)
Selle abil saab sorteerida SQL päringuid kolmel erineval viisil:
- täitmiskordade arvu järgi
- päringu täitmiseks kokku kulunud aeg
- päringu täitmiseks kulunud kõige suurem aeg.
Head kandidaadid on päringud, mida täidetakse kõige sagedamini, sest nende parandamine annab tihti lõppkokkuvõttes suurema võidu. Näiteks, olgu meil kaks päringut,milledest esimest täidetakse päevas kümme ja teist tuhat korda. Optimeerides neist esimest, paraneb kiirus ühe sekundi ja teise puhul saja millisekundi võrra. Kogu ajaline võit ühe päeva kohta on aga tegelikult vastavalt kümme sekundit ja poolteist minutit.
Konkreetse päringu analüüsimiseks saab kasutada SQL Serveri päringu täitmisplaani (Query Execution Plan). See näitab graafiliselt, kui palju mingi päringu täitmine aega võtab ja milliseid operatsioone selle käigus läbi viiakse. Kuvatavat plaani tuleb lugeda paremalt vasakule ja see lihtsustab päringus probleemsete kohtade leidmist.
Päringute optimeerimine
Info saamiseks andmebaasist tehakse päringuid, kus vastavalt seatud tingimustele väljastatakse neile vastavad kirjed. Nende loomisel tuleks jälgida mõningaid lihtsaid võtteid, et vältida üleliigset ressursi raiskamist.
Kirjete pärimisel peab alati kirjeldama, milliseid veerge soovitakse selle tulemusena saada. Näiteks SELECT *(vali kõik veerud) mõjub jõudlusele negatiivselt: kui tabelis on kümme veergu, kuid vaja läheb neist ainult kahte. Sellisel juhul on tegemist ebavajaliku ressursiraiskamisega kahel põhjusel: 1)andmebaas saadab rakendusele rohkem infot kui vaja, 2) muudab indekseerimise keeruliseks.
Tingimuste kirjutamisel tuleks alati küsida seda, mida tahetakse. Mitte vastupidi.
Kõiki päringuid peaks hoidma andmebaasile võimalikult lähedal, kuna nii saadakse neile ka kiirem vastus, sest need asuvad andmetele lähemal võrreldes rakendusega.
Talletatud protseduurid
Talletatud protseduurid on põhimõtteliselt kogum juba varem valmis kirjutatud SQL päringuid, mis on koondatud üheks hallatavaks blokiks. Igat loodud protseduuri kompileeritakse (toimub automaatselt) ühekorra ja peale seda luuakse päringu täitmise plaan, mida hoitakse mälus. Edaspidi võetakse päringu täitmiseks see plaan juba mälust ning seetõttu on ka nende täitmine kiirem. http://www.tech-faq.com/stored-procedure.html + SQL Server Bible(Lk 610)
Kas peaks siia hoopis loetelu tekitama? Nagu punkt1..punkt2.. punkt3
Hästi kirjutatud protseduurid on väga kiired, kuna nad asuvad andmete lähedal. Neid on lihtne testida ja hallata võrreldes veebirakendustes loodud päringutega. Talletatud protseduurid on turvalised, kuna kasutavad parameetreid, mis antakse neile kaasa ja nii kaob SQL injektsiooni oht. Rakenduse loojatel on samuti lihtsam kutsuda välja protseduur, mille sisendiks antakse parameetrid, kui kirjutada seda päringut veebirakenduses. SQL Server Bible (607)
Kasutades protseduure on lihtsam jälgida päringute täitmist ja ajakulu, võrreldes tavalise SQL päringuga, mis tuleb väljaspoolt andmebaasi. Kuna talletatud protseduuri väljakutsumiseks antakse kaasa ainult parameetrid, siis on ka edastatav andmemaht väiksem.
Kirjutades protseduure on hea praktika lülitada COUNT välja kasutades käskuSET NOCOUNT ON
(LK
Lisaks tuleks vältida kursoreid. Kuigi nad on väga paindlikud ja võimaluste rohked, tuleb nende kasutamisel maksta ränka hinda jõudluses.
Kui neid kasutatakse protseduurides, siis optimeerimiseks tuleks alustada nende eemaldamisest.
Kas võin tuua näite SQL Server Bible'st?
Indekseerimine
Indekseerimine on nagu raamatu sisukord. Kui soovitakse leida vajalikku infot, vaadatakse eelkõige sisukorda ning leitakse õige koht. Samamoodi käiakse pidevalt andmebaasist infot pärimas. Tabel ilma indeksita on nagu raamat sisukorrata - millegi leidmiseks peab lehitsema läbi terve raamatu, et leida õige koht, mida otsitakse. Loomulikult on see ajaliselt kulukas protsess. Kui andmebaasis on tabelid õigesti indekseeritud toimub otsimine nagu raamatu sisukorrast (kiiresti).
Indekseid on kahte tüüpi - klasterdatud ja klasterdamata. Klasterdatud indekseerimiseks on ideaalsed väljad tabelite primaarvõtmed kahel põhjusel: 1) see väli on alati unikaalne 2) infot otsitakse tihti selle võtme järgi. Vaikimisi luuakse primaarvõtme veerule alati klasterdatud indeks. Selle loomiseks käsitsi tuleb kasutades SQL lauset:
CREATE UNIQUE CLUSTERED INDEX index_id ON TABLE (veeru_nimi)
Tabeliveerg, millele see luuakse, peab olema alati unikaalne.
Mitte klasterdatud indekseerimise puhul ei pea väli olema unikaalne. Luuakse lausega: CREATE INDEX voti ON tabeli_nimi(veeru_nimi)
CREATE INDEX v0ti ON tabeli nimi(veerg) include ( tabeli_veerg1, tabeli_veerg2,..).Sobib eriti veergudele, kus kasutatakse GROUP BY, COUNT(*) päringuid.
Indekseerimiseks ei sobi väljad, mis on väga mahukad. Näiteks nVarchar(200), mis võtab palju ruumi ja indeksite loomine on mahukas protsess.
Indekseerides tabeli veerge ilma analüüsita, võib see mõjuda jõudlusele hoopis negatiivselt, kuna õigete ridade leidmiseks peab ikkagi tegema lisapäringuid. Selle vältimiseks tuleks jälgida päringu täitmise plaani, mis näitab, kuidas päringuid läbi viiakse ja kas loodud indekseid kasutatakse. Nii võib leida kohti, kus need on küll loodud, kuid küsitakse rohkem kirjeid kui indeksiga kaetud on.
Indekseerimisel tuleb arvestada sellega, et nende loomisel peab maksma natuke hinda ka jõudluses. Sellest tulenevalt tuleks kaasata indeksitesse minimaalselt välju. Mida rohkem on välju, seda kulukam on indeksite uuesti arvutamine, mis leiab aset iga DDL käsu puhul. Indeksite tabel koosneb lehtedest ja lisades uue sissekande tuleb lehed uuesti luua. Eriti halvasti mõjub see siis, kui uus sissekanne tuleb indeksi lehtede keskele. Viimane eeldab lehtede uuesti loomist ja nende poolitamist. Seetõttu tuleb hoolikalt kaaluda, kus kasutada rühmitatud indekseid.
Alates SQL Server 2008 versioonist on võimalik kasutada filtreeritud indekseerimist, mis tähendab, et klasterdamata indeksite loomiseks kasutatakse andmetest ainult mingit osa, mis vastab seatud tingimustele. Selle loomiseks on lause:
CREATE INDEX index_id ON tabeli_nimi(tabeli_veerg) WHERE tingimus. Vajadusel saab ka siin kasutada kaetud indekseerimist.
Transaktsioonid
http://msdn.microsoft.com/en-us/library/ff647793.aspx#scalenetchapt14%20_topic9 Valesti kirjutatud transaktsioonid mõjuvad andmebaasi tööle negatiivselt. Selle vältimiseks on levinud praktikad: tuleks vältida pikki transaktsioone, kuna nende ajal toimub tabelis lukustamine. Soovitatav on valideerida enne transaktsioone juba rakenduses andmed, et vältida transaktsiooni ajal vigade tekkimist, mis pikedab neid. Lisaks ei tohiks transaktsioone alustada enne, kui kõik vajalikud andmed on olemas, kuna lukustus lõpeb alles siis, kui kõik andmed on saadetud. Halb näide on näiteks see, kui alustada transaktsiooniga, kuid selle edukaks lõppemiseks on vaja veel kasutaja poolt sisendit. Tabel on lukus seni, kuni kasutaja on sisendi andnud.
Ummik(Deadlock)on situatsioon, kus üks transaktsioon ootab teise ja teine esimese taga. Kindlasti tuleks sättida sellele aegumise piir, kuna vaikeseadetes võivadki need üksteise järgi põhimõtteliselt ootama jääda. Samuti tuleks sättida parallelism üheks. SQL Server Bible 1382.
Täistekstiotsing
Tihti on vaja lõppkasutajatele võimaldada info otsimist. Kuna enda otsingusüsteemi loomine on kulukas protsess, siis sobib seda asendama alguses SQL Serveri FullTextSearch funtsionaalsus. Viimast saab kasutada alates Standard väljaandest ning see töötab indekseerimise põhimõttel. Antud lahendus pole mõeldud otseselt otsingumootoriks, kuid see on väga hea jõudlusega ning täidab igati oma põhiülesannet, hoides samal ajal ressursikasutuse madalana. Kindlasti tuleks seda eelistada algelisele otsingule, kus kasutatae LIKE operaatorit, mis on aeglane. Sama lahendus on hetkel kasutusel Eesti Rahvusringhäälingu .NET portaalide otsingusüsteemides ja on ennast igati õigustanud.
Andmebaasi konfigureerimine
Parimate praktikate kohaselt soovitatakse jätta paljudele seadetele vaikimisi väärtused. Nii töötab server kõige optimaalsemalt ning nende muutmisel võib olla effekt jõudlusele hoopis negatiivne.
Startup Manager Kui soovida andmebaasist kätte saada maksimum, siis võib SQL Server Configuration Manager'is lisada Startup Parameters alla parameetri -x, mis võimaldab maksimaalselt jõudlust. Selllel on aga üks väga suur miinus. Nimelt lülitatakse kõik monitoorimisvõimalused selleks välja ja jõudlusprobleemide jälgimine ja otsimine muutub peaaegu võimatuks.
Ühenduste automaatne sulgemine(Auto Close) Ühenduste automaatse sulgumise korral vabastab SQL SERVER kõik selle andmebaasi ressursid, peale viimase aktiivse ühenduse sulgumist (sh päringu täitmise plaanide ja kompileeritud talletatud protsetuuride kustutamist). Vabanenud ressursse saavad kasutada teised andmebaasid. Pealtnäha tundub selline tegevus optimaalne, kuid tegelikult on see kindel viis, kuidas SQL Serveri töö hävitada. Paljud rakendused sulgevad ja avavad ühendusi korduvalt. Uute ühenduste tekkimisel tuleb uuesti laadida, kompileerida protseduurid ja arvutada päringu läbiviimise plaanid. See tõttu peaks ühenduste automaatne sulgemine olema keelatud, mis on ka kõigis SQL Serveri versioonides vaikimisiväärtuseks, välja arvatud SQL Express väljaandes.
Ühenduste automaatset sulgemist saab kontrollida graafiliselt Management Studiost või käsuga:ALTER DATABASE ANDBEMAASINIMI SET auto_close ON/OFF.
See peaks olema lubatud ainult siis, kui tegemist on andmebaasiga, mis hoiab endas arhiivi ja kasutatakse väga vähe.
Automaatne kahanemine (Auto Shrink) Kui see võimalus on sisselülitatud, siis juhul kui andmebaasil on üle 25% vaba ruumi, toimub andmete ja logifailide kahandamise operatsiooni. See protsess on kulukas ja samas hakkavad need failid hiljem nagunii kasvama. See põhjustab faili fragmenteerumist operatsioonisüsteemi tasandil. Selle saab välja lülitada käsuga:
ALTER DATABASE Andmebaasinimi SET AUTOSHRINK OFF;
SQL Server Bible 2008 lk 920
ASP.NET tehnoloogiast tulenevad optimeerimisvõimalused
Konfiguratsioon
Konfiguratsiooni hoitakse web.config failis. Selle näol on tegemist infoga veebirakenduse seadistuse kohta. Näiteks: andmebaasiga ühenduse loomiseks vajalikud parameetrid või kuidas toimub rakenduse kompileerimine. ASP.NET kasutab selles failis olevat infot, et luua rakenduse ülesehitus.
Kui testkeskkonnas siluda rakendust, peaks kindlasti selles failis parameetri "compilation debug" väärtus olema true. Vigade esinemise korral on sel juhul neid lihtne leida. Rrakenduse live serverisse tõstmisel peab jälgima, et silumine oleks kindlasti välja lülitatud. Vastasel juhul kompileeritakse pidevalt veebirakendust iga lehe laadimise ajal uuesti ja see omakorda kasvatab protsessori ja mälu kasutust. Kõige kindlam viis sellise olukorra vältimiseks on muuta serveris asuvat machine.config faili ja lisada parameeter deployment retail="true". Nii on kindel, et ükski veebiaplikatsioon ei kasuta antud serveris silumist. Ainukeseks miinuseks selle puhul on, et vea ilmnemisel ei kuvata vea täpset asukohta (rea numbrit ja veakirjeldust).
Lisaks tasub web.config faili lisada väljundipuhvri erinevad profiilid. Sellega saab määrata, kui kaua lehte serveri mälus hoitakse. Kui rakendusele on tulemas suur koormus, saab ühest kohast muuta kõikide väljundite kehtivuse pikkust, mis kasutavad konkreetset profiili.
Viewstate
Viewstate'i kasutatakse, et hoida väärtusi ASP.NET tööriistade (controls) objektide kohta. Lehe laadimisel genereerib ASP.NET ühe peidetud välja, mis kannab nime __VIEWSTATE, kus on see info sees. Nii on võimalik antud väärtuseid kasutada ka peale kliendi-serveri vahelist suhtlust, kui toimub tagasipostitamine (postback). Hoides selles suurel hulgal andmeid, kasvab seetõttu ka lehe suurus ning selle laadimise aeg. Arvestama peab ka sellega, et lehe laadimisel tuleb viewstate'is olevaid andmeid serialiseerida ja deseriaaliseerida. Lisaks võib see vähendada mäluhalduse(GC) efektiivsust. Sellepärast tuleb selle kasutamisega olla ettevaatlik ja eemaldada kohtadest, kus seda vaja ei lähe, kuna see mõjub jõudlusele halvasti. Näiteks genereerivad kõige rohkem viewstate'i ASP.net enda tööriistad nagu Listview ja Gridview. Lehel sisalduva viewstate'i hulga analüüsimiseks on hea tööriist ASP.NET ViewState Helper, mis töötab Firefoxi ja Internet Exploreriga. Selle abil on võimalik näha, kui suure osa moodustab kogu lehe suurusest viewstate.
Vaikimisi on see ASP.NET'is igal pool sisse lülitatud. Soovitatav on see välja lülitada kohtades, kus ei toimu serveri poolseid kontrolle ja ei kasutata tagasipostitamist (postback). Seda saab välja lülitada erinevatel tasemetel: serveris (machinge.config), veebirakenduses (web.config), lehel<%@ Page EnableViewState="false" %>
Kui lehel on lubatud viewstate ja toimub tagasipostitus (postback), siis tuleb seda kontrollida kasutades IsPostBack() meetodit. Viimane teeb kindlaks, kas tegemist on tagasipostitamisega (postback). Kui on, siis pole vajadust enam andmeid uuesti pärida, vaid kasutada juba olemasolevaid ja võtta need viewstate'is.
ASP.NET enda tööriistad
Enimkasutatavad tööriistad on tihti GridView, Listview ja Repeater. Neid kasutatakse tihti erinevate vaadete loomiseks. Esimesed kaks neist genereerivad suurel hulgal viewstate'i, sisaldes väga palju funktsionaalsust. Selle tõttu peab alati valima, milliseid tööriistu kasutada. Kui eesmärgiks on tavalise listi loomine (näiteks uudiste), siis peab kindlasti viewstate'i keelama ja kasutama võimalusel Repeater' it, kuna ListView funktsionaalsust tegelikult vaja ei lähe.
Nende kasutamisel tuleks tähelepanu pöörata väärtuste kuvamise viisile. Levinud on selleks kasutada võimalust:<%#Eval("fieldname")%>
<%#((MyClass)Container.DataItem).field1%> <!-----Klass----!>
<%#((DataRowView)Container.DataItem).field1%>.<!---DataTable---!>
ASP.NEt Site Performance 76 Ainuüksi 10 rea lisamisel võib kiiruse vahe olla enam kui kümnekordne, viimase variandi kasuks mõõdetuna ticksides. Selle kasutamisel peab arvestama, et muutes näiteks klassinime, tuleb muutma seda ka kohas, kus päritakse välja väärtuseid.
ASP.NET genereerib automaatselt HTML'i kõikidele väljadele ID'd, kui need on ka koodis määratud. Näiteks kui kasutada pildikomponenti parameetritega<asp:Image ID="imgMainItem" runat="server"/>
id="ctl00_leftColumn_ctl00_Vaikekategooria3_imgMainItem"
//....
imgMainItem.Src="pilt.jpg";
imgMainItem.ID=null;
//....
Puhver
Andmete talletamine puhvris on üks lihtsamaid viise, kuidas muuta veebirakenduse ja ka andmebaasi tööd kiiremaks. See võimaldab hoida enimkasutatavaid objekte mälus. Sellest andmete kättesaamine on lihtsam ja kiirem, kui selle pärimine pidevalt andmebaasist või kuskilt mujalt. ASP.NETis on kasutusel väljundi puhverdamisliides hoidmaks mälus objekte ning väljundipuhver, kus salvestatakse serveri mällu terve leht. Nende mõlema meetodi kasutamisel peab arvestama, et vajalike andmete/lehtede hoiustamiseks kasutatake serveri mälu. Seetõttu peab läbi mõtlema, milliste andmete talletamine mälus on kriitiline. Seda eriti juhul, kui serveril on mälu vähe. Head kandidaadid puhverdamiseks on lehed/andmed, mida kasutatakse kõige rohkem või mille kätte saamine on väga kulukas protsess. Enamasti on selleks näiteks esileht ja mõned suuremad listid ning otsingutulemused.
Väljundi puhverdamisliides ja väljundipuhver on küll kaks erinevat mõistet, kuid põhimõte on neil siiski sarnane. Mõlemale on võimalik ette anda aeg, kui kaua aega neid serveri mälus hoitakse. Lisaks saab mõlema puhul kasutada SqlCacheDepencyt, mis võimaldab jälgida, kas andmebaasitabelites on muudatusi toimunud. Mälust kustutakse andmed, kui jälgitavas tabelis toimub muudatus.Selle toimimiseks peab andmebaasis lubama tabelitel SqlCacheDependency ja ka web.config failis kajastama seda. Selles saab määrata, kui tihti kontrollitakse, kas andmebaasitabelites on toimunud muudatusi.
http://www.asp.net/data-access/tutorials/using-sql-cache-dependencies-vb http://msdn.microsoft.com/en-us/library/system.web.caching.sqlcachedependency.aspx
Võimalus on kasutada ka mitme tabeli jälgimist. Soovitatav on vaadelda tabeleid, milles ei toimu tihti muudatusi. Vastasel juhul on puhver pidevalt tühi ja andmete saamiseks tuleb siiski päringuid teha. Sellisel juhul tuleks anda ajaline intervall, mille tagant andmeid uuendatakse. http://msdn.microsoft.com/en-us/library/system.web.caching.sqlcachedependency.aspx.
Väljundipuhvri kasutamine on kiirem, kuna selle puhul on lehe töötsükkel lühike. Alguses kontrollitakse, kas leht on serveri mälus olemas ja kui see eksisteerib seal, siis see saadetakse kasutajale. Väjundi puhverdamisliidese puhul aga toimub terve lehe elutsükkel. (See on kirjeldatud peatükis ASP.NET veebirakenduse põhikomponendid ja töötsükkel)
Väljundipuhver
http://msdn.microsoft.com/en-us/library/xadzbzd6.aspx Väljundipuhvri kasutamisel salvestatakse terve dünaamiliselt loodav leht serveri mällu. Peale seda kuvatakse seal olevat lehte. Seda saab kasutada nii terve .aspx lehtede salvestamiseks kui ka usercontrolide puhul. Väljundipuhvri jaoks tuleb lisada järgnev kood lehe ülaossa:
< %@ OutputCache Duration="60" VaryByParam="None" % >
Need kaks parameetrit on alati kohustuslikud. Kestvus(Duration) näitab kui pikka aega lehte serveri mälus hoitakse ja VarByParam parameetriks saab anda päringustringi(d). Lisaks on levinumad parameetrid veel:
- Shared="true/false" - saab kasutada ainult usercontrollide puhul. Kui true, siis cache'itakse see kõikidel lehtedel.
- CacheProfile="profiilinimi" - konfigratsuoonfailis asuv väljundpuhvri profiil.
- SqlDependency ="adnmebaasi/tabeli paar" - defineeritakse andmebaasi /tabeli paarid, mille muutumise korral leht serveri mälust kustutakse. http://msdn.microsoft.com/en-us/library/hdxfb6cy.aspx
- VarByCustom ="nimi" - võimaldab kasutajal luua endal puhverdamise meetod
- VarByParam="parameeter" - saab anda ühe või mitu päringustringi väärtust, mille põhjal leht salvestatakse väljundpuhvrisse.
VaryByCustom'i, kasutamiseks tuleb Global.asax failis ülekirjutada GetVarByCstomString meetod: Näiteks:
public override string GetyVarByCustomString(HttpContext context, string custom){
if(custom=="weekday"){
return ....
}else{
return base.GetVarbyCustomString(context, custom)
}
}
ASP.NET ei hooli stringi tegelikust sisust, vaid kontrollib seda, kas vastav stringi väärtusega leht on juba serveri mällu salvestatud. Kui on, siis serveeritakse leht serveri mälust, vastasel juhul lisatakse uus lehe koopia mällu.
Kas selle alumise möla peaks ära kustutama? Tegelikult ei ole üldse hea lahendus ju... Või mis? Olen seda saab kasutanud näiteks feedi cache'imiseks, mille loomine oli väga kulukas ja mida tohivad näha ainult teatud IP aadressitega kliendid. Tavalise OutPutCache'i lisamine on välistatud, kuna kui võõra IP'ga klient tuleb, näeb ta ikkagi feedi sisu, leht on serveri mälus ja outputcache'i puhul lehe eventeid ei käivtata. Teine halb asi, mis võib juhtuda on kui võõra IP'ga klient tuleb siis kui lehte pole veel serveri mälus.Sellel juhul aga läheb terve feed katki, kuna serveri mälllu salvestatakse leht, mis on tühi, kuna sel hetkl käis lehel keelatud IP'ga klient. Lahenduseks oli override'ida GetVarByCustomString meetod ja cache'ida leht IP põhiselt.
Väljundi puhverdamisliides
Cache API puhul ei hoita serveri mälus mitte tervet lehte, vaid soovitud väärtusi, mis lisatakse sinna koodifailis. Näiteks:
Cache.Insert("võti", "väärtus");
Võimalikud parameetrid, mida Cache.Insert meetodi sisendiks saab kasutada on:
- Insert(String, Object) - Lisab objekti mällu.
- Insert(String, Object, CacheDependency) - Lisatakse objekt mällu ja arvestatakse Dependencyga nii faili kui andmebaasi puhul.
- Insert(String, Object, CacheDependency, DateTime, TimeSpan) - Lisatakse objekt mällu koos aegumisreeglitega.
http://msdn.microsoft.com/en-us/library/system.web.caching.cache.insert.aspx Selle abil saab vähendada väärtuste pärimiseks tehtavaid päringuid. Enne väljundipuhvrist informatsiooni välja võtmist, tuleb alati kontrollida, kas vastava võtmega on seal üldse midagi olemas, kuna vahepeal kustutakse serveri mälus hoiustatud väärtusi. See leiab aset näiteks juhtudkel, kui serveril on vähe mälu, objekt aegub või muutub dependency.
Kontrollida saab näiteks nii:
if(Cache[key]!=null){
}
http://msdn.microsoft.com/en-us/library/ms178597.aspx
.NET raamistiku vahenditest tulenevad optimeerimisvõimalused
Koodi optimeerimine ei puuduta ainult selle kirjutamist, vaid ka viisi, kuidas seda teha. Juba lihtsamate praktikate järgimine võib tagada rakenduse kiirema töötamise. Tuleks vältida kordusi, kuna see genereerib liiasust ja võtab ilmaasjata mälu. Objektid tuleks initsialiseerida võimalikult hilja:alles siis kui neid kasutatakse. Nende loomine võtab küll vähe aega, kuid nad allutavad endale seniks mälu kuni neid enam ei vajata. Seda teemat puudutab autor peatükis Mäluhaldus.
.NET enda vahendite kasutamine
Erinevate andmetöötlusprotsesside jaoks tuleks eelistada .NET'i enda olemasolevaid meetodeid, kuna need on tihti kõige optimeeritumad. Väikeste andmehulkade puhul ei pruugi ajaline vahe välja paista, kuid mahukamate operatsioonide puhul võib olla see märgatav.
Näiteks väga mahukate stringide liitmisel, tuleks kasutada StringBuilderit ja tema append meetodit.
string s = "TestSona";
string temp="";
for (int i = 0; i < 15000; i++)
{
temp += s;
}
Täitmiseks kulus: 0.7213204 sekundit.
StringBuilder sb = new StringBuilder();
string s = "TestSona";
for (int i = 0; i < 15000; i++)
{
sb.Append(s);
}
Täitmiseks kulus: 0.0003441 sekundit.
Samad põhimõtted kehtivad ka teiste operatsioonide kohta nagu näiteks stringide ja kuupäevade võrdlus.
SQL Site Performance lk 79
Veahaldus
Veahaldus on kulukas protsess ja selle valesti kasutamine võib maksta väga valusalt kätte jõudluses. Näitena kasutab autor Guid'i sõelumist (parse). Tegemist võib olla reaalse situtatsiooniga, kus päringustringist saadakse väärtus ja on vaja kontrollida, kas tegemist on õiget tüüpi muutujaga. Selleks on kaks võimalust: kasutada tavalist try-catch veahaldust või meetodit TryParse(). TryParse proovib sisendiks antud parameetrit parsida ja kui see õnnestub, siis tagastab true ja parsitud väärtuse. Kui see toimub edukalt, töötavad mõlemad variandid sama kiiresti. Kui see ei õnnestu, on TryParse tunduvalt kiirem.
for(int i=0; i<5000; i++){ Guid temp; try { temp = Guid.Parse("asd-454-as23-a2322-asdasdasd-afgh123"); } catch { } } for(int i=0; i<5000; i++){ Guid targetGuid; if(!Int32.TryParse("xyz", out asd-454-as23-a2322-asdasdasd-afgh123)){ } }
Tulemus: Esimese variandi jaoks kulus 0.2146621 ticksi, TryParse jaoks 0.0010329 sekundit. Vahe on umbes kahesaja kordne. Lisaks on sellises situatsioonis try-catchi kasutamine väga väär, kuna see on siiski loodud ainult vigade töötlemiseks nagu näiteks andmebaasiühendus eavamine. Kindlasti ei tohiks kasutada seda programmis tingimuste täitmise kontrolliks, sellele tuleks eelistada kontrolle.
Tsüklid
Kasutades foreachi on küll mugav koodi kirjutada, kuid arvestades jõudlust ei ole see kõige parem variant, kuna listi läbikäimiseks kasutatakse enumeraatorit ja see tõttu on see ka kulukas. Sellele tuleks eelistada for tsüklit, mis on optimaalsem. Lisaks tuleks viimast kasutades hoiustada listi pikkus muutujas, et iga iteratsiooni ajal ei peaks seda uuesti arvutama, mis on küll väike, aga siiski ressursi raiskav operatsioon. Samuti ei tohiks küsida välja iga iteratsiooni ajal välja väärtusi, mis on kõik aeg konstantsed, vaid defineerida need enne tsüklit näiteks objektide puhul. ASP.NEt site performance Lk80
Strukt ja klass
Võimalusel tuleks eelistada struktide kasutamist, kuna need annavad juurde jõudlust. Põhjuseks on nende erinevus mälukasutuses. Struktid paiknevad alati pinus(stack), peale meetodi täitmist kustutatakse need kohe ära. Klasside puhul on tegemist 'reference' tüüpi väärtustega, mille jaoks läheb lisaks vaja veel aadressi(tüüpobjektpointerit), sünkroniseerimisblokki(alati olemas), GC vajalikud väljad(bitid) ja alles siis on kirjeldatud väärtused. Näiteks juhul, kui on defineeritud strukt ja objekt, millel mõlemal on ainult üks väli ja see on täisarvu tüüpi, siis objekti puhul võtab üks täisarvu väärtus kolme täisarvu jagu ruumi. Strukt aga ainult ühe. Ka nende meetodite väljakutsumine on erinev, kuna strukt on väärtustüüpi, siis teab kompilaator alati mis tüüpi väljaga on tegemist. Objekti meetodi väljakutsumisel viitab see aga tüübi tabelile. Struktidel on aga ka piirangud, kui neid kasutada ei saa. Nende puhul ei ole pärilust(inheritance) nagu klassidel. Lisaks ei saa seda olemasolevast klassist ega struktist tuletada, küll aga saab implementeerida interface'ist. http://msdn.microsoft.com/en-us/library/aa288471%28v=vs.71%29.aspx + hennu loeng. 00:43 H.Sarv.
Listid
Kollektsioonide kasutamist tuleks alati võimalusel vältida, neile tuleks eelistada massiive, mis on kõige kiiremad. Kui see pole aga võimalik, on soovitatav kasutada Genereerikuid nagu näiteks List või Dictionary. Viimane on eriti kiire kui listist on vaja otsida konkreetseid väärtuseid, kuna tegemist on võti-väärtus paariga. Lisaks saab võtme välja abil välistada duplikaatide esinemist, kuna see peab olema unikaalne. Listi loomisel tuleks anda ette ka selle suurus. Kui seda mitte teha, siis peale seda kui listis saab kohtade arv täis, korrutatakse olemasolev list kahega ja pannakse see Listile uueks pikkuseks. Samuti tuleks sorteeritud listile eelistada List'i, mis sorteeritakse lõpus kasutades Sort meetodit. Vastasel juhul toimub listi sorteerimine kõik aeg, kus sinna lisatakse uus element.
http://msdn.microsoft.com/en-us/library/ms172181%28v=vs.80%29.aspx + hennu loeng. Samas soovitab üldse massiividele üle minna.
Mäluhaldus
http://msdn.microsoft.com/en-us/library/ff647790.aspx#scalenetchapt05_topic5 Kui luuakse uus objekt, siis peale new väljakutsumist eraldatakse sellele mälu. Objekti kasutatakse ja ta "sureb" peale seda, kui tema väärtus sätitakse nulliks või enam ei kasutata. See järel vabastatakse objekti poolt kasutatud osa mälust ja seda saavad tarbida teised objektid. Need tuleb luua alati nii hilja kui võimalik, sest nii säästetakse mälu kasutuamist ja nii ei teki ohtu, et see säilib kaua. Peale seda kui objektiga on toimetused tehtud, pole seda enam vaja ning see tuleks "ära visata" ehk väärtus võrtsustada nulliga. Nii teab Garbage Collector, et seda objekti enam ei vajata ning saab selle varakult ära koristada. Kogu mälu jagatakse neljaks generatsiooniks. Kõik värsked objektid asuvad mälu nullindas generatsioonis. selle täitumisel kutsutakse välja Garbage Collector, mis hakkab seda koristama. Kõik objektid, mis sellele ajal ei osutu prügiks(need, mida veel kasutatake), tõstetakse esimesse generatsiooni, kuna nad on vajalikud. Kui nullindas generatsioonis ei ole midagi kustutada, liigutakse esimesele tasemele. Finalizerite loomine objektidele on väga ebasoovitatav, kuna nad jäävad prügi koristamise käigus ellu. Nad tõstetakse Finalizer qeuesse ja nendeni jõutakse alles järgmisel prügikorstamisel. Eelistatav konstruktsioon on "using", mis hoolitseb selle eest, et selle sees tehtud objekt kustutakse peale selle lõppu. http://msdn.microsoft.com/en-us/library/ff647790.aspx#scalenetchapt05_topic5
Leitud võimaluste rakendamine
Töö praktilises osas tegeleb autor leitud optimeerimisvõimaluste rakendamisega ja tulemuste analüüsimisega. Läbiviidavad muudatused puudutavad eelkõige ERR'i teise põlvkonna .NET portaale news.err.ee ja rus.err.ee
Testimiseks luuakse virtuaalmasin, mis on antud lahenduste testkeskkonnaks. Serverina kasutatakse Windows Server 2008 R2 Standard ning andmebaasimootoriks on SQL Server 2008 R2 väljannet. Lisaks paigaldatakse ka Visual Studio 2010 Ultimate, millega saab veebirakenduses läbi viia muutusi erinevate testide jaoks. Koormuse simuleerimiseks veebirakendusele kasutatakse Apache WampServerit. Iga koormustest kestab 400 sekundit. Selle käigus jälgitakse, kui palju päringuid suudab server keskmiselt sekundis teeninda ning kui palju võtab aega ühe päringu täitmine. Samuti pööratakse tähelepanu SQL Serveri ja IIS'i protsessori ressursikasutusele testide ajal. Andmebaasiks on kasutusel oleva andmebaasi koopia ja rakendused on testmise alsutamise hetkel ka reaalselt kasutusel.
Põhjalikult uuritakse erinevate optimeerimisvõimaluste kasutamist portaalis rus.err.ee, kuna viimasega on esinenud suurte koormuste korral kõige rohkem jõudlusprobleeme. Esmajärjekorras rakendatakse ASP.Net tehnoloogiast tulenevaid optimeerimisvõimalusi. Võrreldakse milline on mõju jõudlusele väljundpuhvri ja puhvri programmeerimisliidese kasutamise korral ning kumba neist tuleks eelistada. Nende testimiste käigus tehakse andmebaasile päringuid, mida analüüsitakse hiljem. Vaadeldakse neist enimtehtavaid ning analüüsitakse, kuidas saaks neid parandada.
Sellele järgneb eelnevate testide tulemuste analüüs ning vastavalt nendele teostatakse portaali optimeerimine. Tähelepanu pööratakse esilehele ja kategooriavaadele, kuna need on ERR portaalide kõige mahukamad osad ning mitmed neil asuvad komponendid korduvad ka teistel lehtedel. Samuti vaadatakse üle kas .NET enda vahenditest tulenevaid optimeermise võimalused ning vajadusel püütakse neid rakendada. Lähtudes rus.err.ee portaali optimeerimisel tehtud järeldustest, on neid võimalik rakendada ka teistes Eesti Rahvusringhäälingu portaalides, mis kasutavad teise põlvkonna administreerimisliidest. Töö lõpus võrreldakse olemasoleva lahenduse ja töö käigus optimeeritud lahenduste jõudlust.
Antud diplomitöö käigus teostab autor muudatusi kindlasti veebirakenduses, vajadusel ka andmebaasis.
Esileht ilma optimeerimata
Kõige esimesena testitakse rakendust ilma väljundpuhvrit ja puhvri programmeerimisliidese kasutamiseta. See tähendab seda, et iga lehe uuesti laadimine põhjustab uued päringud andmebaasi ja terve lehe töötsükli läbimist. Esilehe puhul Tulemused on näidatud allolevas tabelis.
Testi pikkus | 403.2 sekundit |
Päringuid lehele | 72 |
Sekundis täidetud päringute arv | 0.18 |
Keskmiselt ühe päringu täitmiseks kulunud aeg | 5,642 sekundit |
IIS:
SQL Server:
Väljundipuhver ja puhverdamisliidese võrdlus
Lähtuvalt erinevatest optimeerimisvõimalustest, siis võib väita, et kasutades puhvrit on võimalik koormust andmebaasile ja veebiserverile võimalik vähendada, kuna andmeid ei pea pärima ja töötlema enam nii tihti. Nii saab jõudlusprobleemide esinemise korral vähendada neid kasutades puhvrit. Viimast on olemas kahte liiki: puhverdamisliides ja väljundipuhver. Autor viib testib neist mõlemat. Selle eesmärk on selgitada välja kui suur ressursikasutuse vahe esineb nende kasutamisel ning kumba neist peaks eelistama.
Antud lähtetingimused testi läbiviimisel: test kestab 400 sekundit või kuni 50 000 päringu täitmiseni. Testitavaks leheks on rubriigivaade, kus kuvatakse antud kategooria viitekümmet viimast uudist. Selle läbiviimise ajaks eemaldatakse lehelt teised komponendid. Puhvri pikkuseks on mõlema variandi puhul 40 sekundit.
Lähtuvalt peatükist "x.x", kus tuvustati ASP.NET veebirakenduse töötsüklit, peaks olema väljundpuhvri kasutamine kiirem, kuna lehe töötsükli täitmine lõpetatakse juba Algus faasis, kui serveris on leht olemas. Puhverdamisliidese puhul aga kontrollitakse alati, kas puhvris on soovitud andmed olemas ja see järel leiab aset DataBind, kus andmed salvestatakse komponenti.
Väljundipuhver | Puhverdamisliides | |
---|---|---|
Testi pikkus | 158.18 sekundit | 402.85 |
Päringuid lehele | 50 000 | 45522 |
Sekundis täidetud päringute arv | 316.1 | 113 |
Keskmiselt ühe päringu täitmiseks kulunud aeg | 3.1ms sekundit | 8.8ms |
Antud testi tulemuste põhjal võib järeldada, et võimalusel peaks eelistama alati väljundpuhvri kasutamist, kuna selle kasutamine annab üle kahekordse kiirusevõidu.
Esileht väljundipuhvris
Lähtuvalt eelmises peatükis saadud informatsioonist, lisatakse esileht väljundpuhvrisse 40 sekundiks. Võrreldes eelneva testiga, kus puhverdamist ei kasutatud üldse, on tulemuste paranemise arv märgatav. Samas märgib autor, et sellise lahenduse kasutamine pole kindlasti aktsepteeritav. Nagu graafikutelt on näha, siis puhvri tühjaks saamisel andmete uuesti pärimine toob endaga kaasa nii veebi- kui andmebaasiserveris väga järsu ressursikasutuse kasvu. Arvestades asjaolu, et ERRis on ühel serveril veel mitu teist portaali, tuleks sellist situatsiooni vältida, kuna erinevate portaalide puhvrid võivad tühjaks saada samal ajal. See põhjustab kordades suurema koormuse, kui ühe portaali puhul. Võimalikult hea tulemuse saamiseks tuleks kasutada osalist väljundpuhvrisse lisamist, kus komponentidele antakse ette erinev aegumisaeg. See peaks tagama autori arvates lehele ühtalsema koormuse jaotamise. Seetõttu ei ole soovitatav kasutada ka SQLCacheDependencyt komponentides, mille uuendus sõltub sama andmetabeli muudatustest. Muidu tekib sarnane situatsioon nagu antud testis:Hetkel kui jälgitavas tabelis toimub muutus, tühjenevad kõik puhvrid kõikidel komponentidel, mis seda kasutavad. Antud organisatsiooni puhul on see eriti aktuaalne, kuna samu andmebaasitabeleid kasutavad 8 erinevat portaali.
Samuti ei saa kasutada väljundpuhvrit kohtades, kus toimub lehele tagasipostitus või toimub andmete täitmine näiteks ruutingu tingimusest lähtuvalt, sest lehe töötsükkel lõpetatakse juba algusfaasis, mis välistab edasise andmete töötlemise. Viimased komponendid on Eesti Rahvusringhäälingu portaalides näiteks kommenteerimisvormid, küsitlus ning "Samal teemal" kast.
Testi pikkus | 301.62 sekundit |
Päringuid lehele | 50 000 |
Sekundis täidetud päringute arv | 165,77 |
Keskmiselt ühe päringu täitmiseks kulunud aeg | 0.6 sekundit |
SQL Server:
Andmete sidumine
Nagu autor ka eelpool välja tõi, ei saa kasutada väljundipuhverdamist Eesti Rahvusringhäälingu portaalis mitmel komponendil. Üheks selliseks on ka kategooriavaade, mille sisu täidetakse vastavalt ruutingu esimes kohal asuvale väärtusele. See ütleb, millise rubriigiga on hetkel tegu. Selleks, et neid andmeid mälus hoida, tuleks kasutatada puhverdamisliidest, kuhu lisatakse andmetabel, milles kuvatavad väljad asuvad. Väljakuvamiseks kasutatakse hetkel listivaadet ja Eval operaatorit. Peatükkide 4.3 ja 4.4 põhjal väita, et hetkel on tegemist on ebaoptimaalse ressursikasutusega. Listivaade genereerib lehele ohtralt viewstate'i ja selle funktsionaalsust antud lahenduse puhul tegelikult vaja ei lähe. Eval operaatori kasutamine on samuti kulukas lähtudes leitud materjalidest.
See tõttu asendatakse listivaade kordajaga (repeater) ning Eval("väljanimi") operaatori asemel kasutatakse ((System.((System.Data.DataRowView)Container.DataItem)["väljanimi"] varianti. Kasutatakse 40 sekundilist puhverdamist.
Uus versioon | Vana versioon | |
---|---|---|
Testi pikkus | 394.229 sekundit | 402.85 |
Päringuid kokku | 50 000 | 45522 |
Sekundis täidetud päringute arv | 126.83 | 113 |
Keskmiselt ühe päringu täitmiseks kulunud aeg | 7.885msms sekundit | 8.8ms |
Lähtudes mõõtmistulemustest tuleb tõdeda, et optimaalsem on kasutada materjalidest leitud võimalusi ning neid tuleks rakendada ka mujal.
Andmebaasipäringute optimeerimine
Peale andmebaasipäringute analüüsimist selgus, et praeguse lahenduse korral pole kohati indekseerimisest eriti kasu. Tehtavad päringud võtavad tihti rohkem infot kaasa kui vaja, kuna valitakse kõik veerud. Samuti tehakse kõiki neid päringuid rakenduses ning mitmes osas. Otsitakse üles uudised, nende kategooriad, siis tekst ja nii edasi. Anmdebaasiühendusi avatakse ja suletakse tihti, mis on aega võttev protsess. Autor leiab, et arvestades antud situatsiooni, tuleks luua andmebaasi protseduur, mis tagataks soovitud väärtused. Nii on päringuid lihtsam hallata. Loodav lahendus peaks olema piisavalt paindlik, et seda saaks kasutada ka teistes portaalides.
Läbiviidavad muudatused
Antud veebirakenduse jõudluse parandamiseks luuakse protseduur, mis oleks võimalikult paindlik, et seda saaks kasutada ka teistes portaalides. Peale selle valmimist tuleb olemasoleva lahenduse koodis viia läbi muudatusi. Hetkel on veatöötlemine lahendatu try catch plokkidega kohtades, kus seda tegelikult vaja ei lähe. Erinevad päringud andmebaasi poolele asendatakse loodava protseduuriga, mis suudab anda tagasi kogu info. Selle arvelt peaks kasvama andmebaasist saadavate päringutele vastuste saamine. Puhverdamisel eelistatakse võimalusel väljundpuhvri kasutamist, kuna see on võrreldes puhverdamisliidesega kiirem ja põhjustab veebiserverile vähem koormust. Nagu joonistel näha oli siis hetkel kui puhvrit hakati uuesti täima, tekkis sellel ajal nii veebiserverile kui ka andmebaasile järsult suur koormus. Kuna Eesti Rahvusringhäälingu puhul on ühes serveris mitu erinevat portaali tuleks sellist olukorda vältida. Selleks pannakse puhvri aegumise ajad erinevad, et jagada koormust ühtlasemalt.