Diplomitöö: ASP.NET veebirakenduse optimeermine meediaorganisatsiooni näitel: Difference between revisions

From ICO wiki
Jump to navigationJump to search
Line 58: Line 58:


Kirjutades protseduure on hea praktika lülitada COUNT välja kasutades käsku SET NOCOUNT ON. Viimasega võib sõltuvalt päringu keerukusest võita kuni 17% selle täitmise kiirusest. Vaikimisi on NOCOUNT välja lülitatud ja see tõttu saadab saadab SQL Server kaasa ka alati ridade arvu, mis päringu tulemusena leiti.
Kirjutades protseduure on hea praktika lülitada COUNT välja kasutades käsku SET NOCOUNT ON. Viimasega võib sõltuvalt päringu keerukusest võita kuni 17% selle täitmise kiirusest. Vaikimisi on NOCOUNT välja lülitatud ja see tõttu saadab saadab SQL Server kaasa ka alati ridade arvu, mis päringu tulemusena leiti.
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 kasutatakse kursoreid, siis nende optimeerimiseks tuleks alustada kursorite eemaldamisest.

Revision as of 15:17, 3 April 2011

Siin lehel kirjutan oma diplomitööd. Alustan 19.märtsil probleemi kirjeldusega.

1. Probleemi kirjeldus

1.1 Olemasolev lahendus

Meediaorganisatsiooni näitena kasutatakse Eesti Rahvusringhäälingut, mis tegutseb internetimeedia turul ja haldab enam kui kahtekümment portaali. Need on erineva sisuga, kuid kõikide näol on tegemist põhimõtteliselt uudiste portaalidega. Ainus erand on otse, mis võimaldab kasutajatel vaadata veebist internetiülekandeid. Ettevõtte eesmärgiks on laiendada oma tegevust ja kasutada kõikide portaalide haldamiseks ühtset .NET platvormi. Hetkel kasutavad seda tehnoloogiat pooled portaalid, milledest enamus kasutab .NET4, kuid leidub ka .NET 2 raamistikku kasutavaid rakendusi. Ülejäänud kasutavad PHPd. Hetkel tegeletakse aktiivselt kõikide portaalide ületoomisega .NET 4 raamistikule, mis on ka uute veebirakenduste aluseks.

ASP.NET võimaldab kasutada mitut programmeeriskeelt ühes rakenduses. Antud organisatsioonis kasutatakse nii C# kui ka Visual Basicut. .NET 4 raamistikul asuvate rakenduste näol on tegemist teise põlvkonna portaalidega, mis kasutavad enamus sarnast lahendust. Viimasel puudub aga korralik andmekiht, mille rolli täidab lihtsalt LinqToSql'iga genereeritud andmebaasitabelitest klassid. Kuna hetkel pole veel uut lahendust loodud, peab kasutama olemasolevat.

Andmebaasi platvormiks on SQL Server 2008 R2 Standart väljaanne. Veel mõned kuud tagasi oli kasutusel piiratud võimalustega Express versioon. Veebirakendused töötavad IIS 7.5 peal ja neil on kasutada üks server.

1.2 Probleem

Teise põlvkonna portaalide jaoks loodud lahendus valmis kiirustades, kuna seda oli vaja kiiresti ja programmeerijaid vähe. See tõttu puudus oodatava süsteemi kohta analüüs. Rakenduse loomiseks kasutati võtteid, mis kiirendasid küll selle valmimise kiirust, kuid paratamatult kannatas selle all jõudlus. Enne ametlikku kasutuselevõttu ei olnud võimalik teha süsteemile korraliku jõudlustesti, mis näidanuks tema toimimist suure koormuse korral. Sellel hetkel kasutas seda lahendust üks portaal ja .NET lahendusi oli vähem.

Arendusmeeskonda on lisandunud ka noori programeerijaid, kes ei ole piisavalt teadlikud optimeerimisvõimalustest. ASP.NET lahendusi on küll võimalik pealtnäha kiiresti ja kergelt valmistada, kuid jättes optimaalse ressursikasutuse jälgimise tagataustale, mõjub see rakenduse jõudlusele hävitavalt.

Poole aasta jooksul on lisandunud uusi .NET portaale, milledest enamus kasub 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 ressursse, siis mõjutab see ka teiste portaalide tööd. See on kindlasti ka üheks turvanõrkuseks - leides ühel leheküljel ressursinõudliku protseduuri, saab seda kasutada kõikide .NET portaalide töö häirimiseks. Halvimal juhul lõpeb see serveri töö seiskumisega. Täiendavad investeeringud riistvarasse on aga välistatud, et kasvatada serveripargi jõudlust. 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 hakkama ka "uut mootorit". Kuna juba praegu esineb jõudlusprobleeme, tuleb enne seda parandada olemasolevate portaalide jõudlust. Selle tõttu on vaja olemasolevaid rakendusi optimeerida. Lisaks ei pruugi riistvara soetamine alati olla ka lahendus nagu seda näitavad ka meie digiretsept või valimistulemustesüsteem.

Tegemist on tänapäeval väga aktuaalse probleemiga, mis ei puuduta ainult näitena toodud organisatsiooni. Kasutades optimeerimist ei tööta veebirakendused mitte ainult kiiremini, vaid võib ära hoida ka täiendavaid lisakulutusi riistvara soetamiseks, millega loodetakse nii probleeme lahendada.

Metoodika valik ja võimalikud lahendused

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. Eelistatud on Microsofti enda poolt soovitatud lahendused.

ASP.NET rakenduse arhitektuur

Optimeerimises üldiselt

Andmebaasi optimeerimine

Öeldakse, et koodi saab alles siis optimeerida, kui midagi töötavat on juba valmis tehtud. Andmebaaside puhul selline väide aga ei kehti, kuna selle hea jõudluse tagamise üheks tähtsamaks nurgakiviks on korralik disain. Kui andmebaas on halvasti loodud, siis on ka selle optimeerimine keeruline ja sellest pole nii palju kasu. Öeldakse, et päev tööd andmebaasi loomise algusfaasus võrdub hiljem sama tulemuse saavutamiseks kolme kuuga. Andmebaasi jõudluse tagamine ei koosne ainult protseduuride korrigeerimisest ja mõnede seadete muutmitest. Enne selle kallale asumist peab analüüsima üldse seda, mis hetkel toimub - kuidas päringuid täidetakse, kui palju see võtab jõudlust, kas indekseeritud on õiged väljad. Ei saa loota, et suvaline indekseerimine parandab andmebaasijõudlust, vastupidi, selle hoolimatu kasutamine mõjub jõudlusele hoopis negatiivselt. Siiski on mõned põhitõed, mis parandavad andmebaasi jõudlust alates selle loomisest.

Andmebaasi loomine

Nagu eelpool mainitud, algab kõik andmebaasiloomisest. Selle protsessi käigus tehtud otsused mõjutavad väga palju andmebaasi edaspidist jõudlust ja ressursikasutust. Alguses valesti tehtud otsused võivad mõjuda halvasti andmebaasi, kui ka seda kasutava rakenduse jõudlusele. Muidugi on kõige tähtsam andmebaasi loogiline ülesehitus, kuid tähelepanu tuleb pöörata ka kindlasti veergude definitsioonidile, mis tuleb määrata korrektselt ja loogiliselt. Ehk kuupäevad peaksid olema kuupäeva tüüpi, mitte nVarchar või char. Teine punkt mida veerutüüpide loomisel tasub alati läbi mõelda on, kui täpseid andmeid meilt 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 kui tihti on selline täpsus süsteemides vajalik? Jah, tõesti on kohti kus see on väga kriitiline, kuid kindlasti leidub rohkem situatsioone, kus piisab ka minutitäpsusest.

Näiteks uudisteportaalides on avaldamisajad tihti märgitud ainult kuupäeva ja minutitega. Selle jaoks on ideaalne SmallDateTime, mis on minuti täpsusega ja lisaks võtab poole vähem ruumi(4baiti). Lisaks on andmebaasis olemas nüüd täpselt vajalikus formaadis kuupäev ning me ei pea hakkama seda veebirakenduses andmete väljaküsimusel seda omakorda ümber hakkama vormindama, mis säästab veel rohkem ressurssi.

Kindlasti tuleb säilitada aga ka paindlikus ehk tinyint võtab küll 4 korda vähem ruumi, kui Int, aga see eest saab tabelisse kokku tekitada 256 unikaalset kannet kui tegemist on primaarse võtme väljaga.

Selliseid näiteid leidub kõigi andmetüüpide kohta. Ehk enne tabelite loomist tuleks kindlasti tutvuda konkreetse andmebaasimootori dokumentatsiooniga ja teha selgeks, milliseid võimalusi pakutakse ja mida meil täpselt vaja on. Eelpool mainitiud SmallDateTime on saadaval alates SQL Server 2008 versioonist.

GUID

Huvitav on mainida ka GUIDi kasutamist. Jõudluse poolelt tundub olevate GUID'i kasutamine hullumeelne kui võrrelda seda näiteks INT tüübiga. (Ikkagi 16 baiti vs 4 baiti). Samas GUID'iga kaasneb ka kaks plussi. GUID on alati unikaalne, kui INT on unikaalne ainult ühes tabelis. See tõttu on GUID'i kasutamisega välistatud, et kokku viiakse omavahel tabelite veerud, mis tegelikult ei ole omavahel seotud. Teine pluss on see, et GUID ei saa kunagi otsa.

Üks enim levinud argument, miks mitte GUIDi kasutada primaarse võtmena ja eelistada sellele INTi on asjaolu, et see nullib ära klasteeritud indekseerimisega saavutatava jõudlusevõidu. INT kasvab automaatselt ja seega iga uus sissekanne automaatse primaarse võtme kasvamise puhul on viimane, GUID genereeritakse automaatselt ja see tõttu ei pruugi see viimane olla. Iga uus sissekanne nõuab indeksite uuendamist ja see tõttu põhjustab selle kasutamine lehtede poolitusprobleeme ja indeksite fragmenteerumist. Alates SQL Server 2005 versioonist saab selle vastu kasutada funktsiooni NewsequentialID(), mis tagab, et iga järgmine GUID on eelmisest suurem. Seega ei tule uus sissekanne mitte lehe keskele, vaid läheb alati viimaseks. Samas tuleb tõdeda, et kuna GUID kasutab rohkem mälu, siis tekib juurde indekseerimisel rohkem lehti ja indeksite uuendamine on kulukam kui INT tüübi puhul.

Päringute optimeerimine

Info saamiseks andmebaasist tehakse päringuid, kus vastavalt seatud tingimustele väljastatakse sobivad tulemused. Nende loomisel ja kirjutamisel tuleb jälgida mõningaid lihtsaid võtteid, et vältida üleliigset ressursi kulutamist.

Infot küsides peab alati kirjeldama, mida me tahame tagasi saada. Ehk näiteks SELECT * päring võib olla päris korralik jõudlusetapja, olukorras kus meil on tabelis 10 välja, kuid tahame saada kätte neist ainult kahte. Sellisel juhul on tegemist ebavajaliku ressursiraiskamisega. Lisaks on sellisel juhul ka tabelite indekseerimisest väga vähe kasu, kuna kõigi veergude kättesaaamiseks tuleb teha lisapäringuid.

Päringuid kirjutades peaks küsima alati seda, mida meil vaja on. Võimalusel tuleks vältida eitusi.

Andmebaasi töö sõltub väga palju selle ülesehitustest ja konkreetsetest päringutest. Selle optimeerimiseks peab analüüsima juba loodud ja loomisel olevaid päringuid, et näha kuidas nad käituvad. Selle jaoks on soovitatv kasutada SQL Serveri Query Editor'i kus on võimalik näha päringu täitmist kasutades Execution plan'i. Nii on võimalik kindlaks teha, näiteks kas loodud indekseid kasutatakse, kuidas täpselt toimub päringu täitmine ning kui palju see aega võtab. Selle alusels saab vajadusel muuta indekseerimist või päringuid.

Protseduurid

Andmebaasi jõudluse tagamisel on hea praktika protseduuride kasutamine. Hästi kirjutatud protseduurid on väga kiired. Lisaks on neid lihtne testida ja hallata võrreldes ad hoc päringutega. Samuti on need turvalisemad, kuna kasutavad parameetreid, mis antakse neile kaasa. Ka rakenduseloojatel on lihtsam kutsuda välja protseduur, mille sisendiks antakse parameetrid, kui kirjutada ad hoc päringut, mis avab võimaluse SQL "injenction" rünnakuteks ja seega on ka üheks turvariskiks. Viimaseid on ka raske hallata ja asuvad reaalsetest andmetest kaugel.

Kasutades protseduure on lihtsam jälgida päringute täitmist ja ajakulu, võrreldes tavalise SQL päringuga, mis tuleb väljaspoolt andmebaasi. Kuna kaasa antakse ainult parameetrid, siis on ka edastatav andmemaht väiksem. Samuti asub see ka andmetele lähem.

Kirjutades protseduure on hea praktika lülitada COUNT välja kasutades käsku SET NOCOUNT ON. Viimasega võib sõltuvalt päringu keerukusest võita kuni 17% selle täitmise kiirusest. Vaikimisi on NOCOUNT välja lülitatud ja see tõttu saadab saadab SQL Server kaasa ka alati ridade arvu, mis päringu tulemusena leiti.

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 kasutatakse kursoreid, siis nende optimeerimiseks tuleks alustada kursorite eemaldamisest.