webForumDet fria alternativet

Optimering: Databashämtningspool?

30 svar · 1 607 visningar · startad av Lukaspojken

LukaspojkenMedlem sedan maj 20011 312 inlägg
#1

I traditionell asp så tjänade man enormt på att ha en databashämtningspool, dvs en pool där man öppnade databasen, gjorde alla hämtningarna man behövde och sen stängde databasen så fort som möjligt. När jag programmerar i .net i en fyrskiktad miljö så känns det på något sätt fel :) Det blir dock mer struktur men det känns som att det är något som inte riktigt stämmer men jag kanske har fel.

För vi antar att jag ska göra 3 hämtningar i traditionell asp då skulle jag gjort alla hämtningarna direkt Det skulle bli likt ett V där botten på v:et är databasen och topparna presentationsskiktet.

I .net skulle följande exempel se ut enligt följande VVV. En nyfiken fråga som jag har är hur detta påverkar prestandan och skulle någon form av databashämtningspool kunna förbättra det hela en del?

/Lukaspojken

OveRRidEMedlem sedan feb. 200112 078 inlägg
#2

Om inte jag missuppfattat vad du menar, så är det helt enkelt ett datahanterinslager du pratar om.

Typ;
- Presentationslaget
- - Logiklager
(- - - Datahanteringslager)
- - - - Datalager

Det finns ingen anledning till varför du inte skall ha en dataklass eller liknande lager i din applikation i ASP.NET, snarare är ett nästan ett faktum att du skall ha det.

renholmMedlem sedan apr. 20012 266 inlägg
#3

Om vi pratar om Connection pool så hanterar .NET det automatiskt, se länken nedan för mer information:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconconnectionpoolingforsqlservernetdataprovider.asp

LukaspojkenMedlem sedan maj 20011 312 inlägg
#4

-> OveRRidE
Så här ser det ut idag:

1. Presentationsskikt
2. Fasadskikt
3. Affärs/Logikskikt
4. Dataskikt

Hur skulle datahanteringsskiktet fungera? Använder du något sådant idag? Kan du ge ett exempel på hur du använder det.

-> renholm
Tack för tipset! Jag läste lite men jag tror inte riktigt det är det som jag menar. Lite svårt att förklara :)

Vi antar att jag har tre select-satser till en och samma databas. I traditionell asp så skulle man tjäna en hel del på att göra alla dessa hämtningar på en och samma plats, i dvs en "databashämtningspool". Man öppnar databasen, hämtar det man ska hämta och därefter stänger databaskopplingen så fort som möjligt.

Det är underligt om inte samma sak borde gälla för .net. Så min fråga är om man inte förlorar en hel del på att ha lite databaskopplingar här och var i en aspx-sida. Skulle man tjäna på att i tex page-load:en ha ett anrop till en databashämtningspool?

Hoppas det blev lite klarare :)

/Lukaspojken

PDahlenMedlem sedan apr. 2004778 inlägg
#5

Det är det som förklaras i renholms länk. I .Net behöver du inte tänka på det, det sköts automatiskt.
När du kör din första select-sats så öppnar du en connection, när du är klar så läggs den connection i poolen. När du kör din andra select så kollas poolen om det finns någon connection och så återanvänds den.

När det gäller att "ha lite databaskopplingar här och var i en aspx-sida" så är meningen med flerskiktslösningar att du inte har några databaskopplingar i presenatationslagret. De ska ligga i datalagret och anropas av affärslagret. Presentationslagret (aspx-sidan) ska inte ens veta vad datalagret är.

Har skrivit lite om det på http://www.pdc.se/blog/DisplayEntry.aspx?eid=5 om du vill veta mer.

PaceMedlem sedan juni 20019 024 inlägg
#6

PDahlen skrev:

Har skrivit lite om det på http://www.pdc.se/blog/DisplayEntry.aspx?eid=5 om du vill veta mer.

Intressant blog du har, läsvärd. Ser fram emot mer. :)

PDahlenMedlem sedan apr. 2004778 inlägg
#7

Tackar tackar. Mer kommer. :)

LukaspojkenMedlem sedan maj 20011 312 inlägg
#8

-> PDahlen
Om jag inte minns helt fel så skötte traditionell asp detta per automatik också men detta var inte något att rekommendera. Jag kan dock tänka mig att i .net så har man förbättrat detta en del men är det så att den automatiska poolingen är effektivare än den manuella i .net? För jag antar att man kan skötte poolingen på ett manuellt sätt också eller?

PDahlenMedlem sedan apr. 2004778 inlägg
#9

Med ASP så strävade man efter att öppna databaskopplingen, utföra alla databasanrop man behövde på sidan, stänga dbkopplingen och sedan använda resultatet i t.ex. arrayer och dylikt. Man ville ha dbkopplingen öppen så kort stund som möjligt.
I .NET så kan man tänka att visst vill man ha så få dbkopplingar som möjligt men samtidigt så får man utgå från sin design.

Jag lägger ingen tid på sånt här. När jag designar mina applikationer börjar jag nerifrån och designar mig uppåt i mina lager, så som jag beskriver i min blogg.
När man kommer till presentationslagret så ser man på vad sidan behöver för objekt, man skapar dessa objekt (vilket automatiskt innebär att de fylls från databas eller cache) och presentationslagret vet ingenting om databasen eftersom de bara "pratar" med själva objektet.

Ett exempel:
På en sida ska jag visa en lista med nyheter. PL anropar affärslogiken som skapar ett NyhetsList objekt. Affärslogiken kollar om objektet finns i cachen, om inte så anropar det DataLogiken som vet hur databasen ser ut. Genom att använda Microsoft Data Access Application Block så görs anropet och datalogiken skickar tillbaka en DataReader till affärslogiken. Affärslogiken aktiverar en metod som heter NyhetsListan.Fill(myReader). Fill funktionen fyller min collection med nyheter. Nu är samlingen fylld och affärslogiken skickar tillbaka den till presentationslagret som binder den direkt till en repeater.
Om jag t.ex. ska byta databas från SQL Server till MySQL så bygger jag ett nytt datalogiklager.
MS Data Access blocket hanterar databaskopplingen med ADO.NET. Jag petar aldrig i den koden.

Det enda jag gör för att sträva efter färre dbkopplingar är att lägga in objekt i cachen i affärslagret. Men det kräver en del tänk och kunskap för om man cachar fel så blir prestandan lidande.

Min rekommendation är att du läser på om Cache-objektet istället. Det är lösningar som cache, session, state, (dvs. Persistence) som är nyckeln till färre dbkopplingar och i vissa fall bättre prestanda.

GladhMedlem sedan maj 20012 812 inlägg
#10

Rent prestandamässigt så kommer du få en marginell förbättring genom att göra som du säger att skapa en manuell "databashämnintngspool" (konstig ord). Där du spara ihop dina SQL satser och exekverar dem alla på engång.

Ur design och underhållssyfte är det förkastligt och gör arbetet svårare. Det är alltid en avvägning mellan ren rå prestanda mot design, underhåll och återanvändningsbar kod.

Flersiktande lösninger ger oftas lite sämre prestanda, men ökad skallbarhet och bätter förutsättningar för att underhålla och vidarutveckla sin kod.

Är du endast ute efter brutal rå prestanda, så glöm att med siktadelösningar, OOP och annat trams. Kör med en SQLDataReader som du binder till en repeater i din CodeBehind. Blir jobbigt och omständigt, men bäst ur prestanda synpunkt.

Precis som Patrik skriver så skall man tänka mer på sin design av applikationen än prestandan, glöm inte bort prestandan och använd cachade objekt när det finns möjlighet, men gör inte en dålig design för att få lite bättre prestanda om du verkligen, absolut inte måste ha det.

- M

LukaspojkenMedlem sedan maj 20011 312 inlägg
#11

-> PDahlen
"I .NET så kan man tänka att visst vill man ha så få dbkopplingar som möjligt men samtidigt så får man utgå från sin design."

Jag håller med i det du säger men samtidigt tycker jag det vore intressant att se om man kunde ta hänsyn till bra "design" och samtidigt ha en effektiv databashämtning. För det borde vara möjligt.

/Lukaspojken

LukaspojkenMedlem sedan maj 20011 312 inlägg
#12

-> Gladh
"Databashämtningspool" det är ett eget uttryck :)

Jag håller med dig i det du säger men som jag sa till Patrik så tycker jag det borde finns något sätt att ta hänsyn till designen och samtidigt erhålla bättre prestanda.

/Lukaspojken

GladhMedlem sedan maj 20012 812 inlägg
#13

hänsyn till designen och samtidigt erhålla bättre prestanda.

Tyvärr, en renar och bättre design enligt konstens alla regler innebär mer overhead för din applikation: fler metodanrop, fler typomvandlingar, fler kontroller osv osv. I en riktigt uppdelad flerskiktlösning, så har du desutom dela upp dina olika lager på olika maskiner vilket gör att prestanda för att hämta en post blir mycket sämre än om allt låg på en och samma maskin.

Det du vinner är istället skalbarheten, alltså det är enkelt att förbättre antalet användare som kan använda din applikation samtidigt genom att flytta ut de olika lagerna till olika maskiner som på detta vis delar på den belastning som blir. Alltså kan man hantera fler användare, men operation tar längre tid.

Du vinner också återanvändbarhet. Säg att du bygger ditt DAL som du lägger på en egen maskin, detta DAL, tar emot:
1. connectionstring
2. SQL Statment
och returnerar ett datatable.

Varje gång du nu behöver hämta datafrån databasen, så kan du kalla på ditt DAL och skicka med connectionstring och SQL Statments. Du har alltså återanvänt ett helt lager i en applikation och drastiskt minskat utvecklingstiden och därmed kostnaden för att utveckla applikationen, men som sagt prestandan blir lidande... så är det bara.

Sedan måste man ställa frågan. Hur mycket försämrar jag min prestanda om jag gör så här. Är det 1% eller 25% eller kanske 100%. Utefter detta kan man sedan bestämma sig om det är lönt att satsa på prestanda eller om man skall bygga i flerskikt. Min rekomendation är alltid att bygga och designa för flerskikt, och sedan lösa prestandaproblemen efterhand som de dyker upp.

I just ditt fall är skillnaden så liten att det inte knappt är lönt att lägga ner tiden och mödan på att disskutera det :) Det viktiga är att använda sig av connectionpoolen och det gör .NET till dig, att sedan samla ihop SQL satserna till 1 fråga istället för 3 ger dig väldigt liten vinst, även om den finns där.

- Magnus

OveRRidEMedlem sedan feb. 200112 078 inlägg
#14

Hur skulle datahanteringsskiktet fungera? Använder du något sådant idag? Kan du ge ett exempel på hur du använder det.

Det är (beroende på din design) någon slags klass som bara sköter uppdatering, addering och radering av data i ditt datalager, med givna parametrar som t.ex. SQL-statements. Precis som andra skrivit innan mig.

Jag vet inte, men det känns som om det pratas om två olika saker i den här tråden.

Att 'poola' connections är någon som både ASP.NET och ASP gör själva. Det har funkat hela tiden i gamla IIS:en och sker helt transparent.

LukaspojkenMedlem sedan maj 20011 312 inlägg
#15

>Det är (beroende på din design) någon slags klass som bara sköter uppdatering, addering och radering av data i ditt datalager, med givna parametrar som t.ex. SQL-statements. Precis som andra skrivit innan mig.

LP: Okej, då förstår jag. Ett sådant "lager" finns idag.

>Att 'poola' connections är någon som både ASP.NET och ASP gör själva.

LP: Och i asp så var det inte bra att förlita sig på poolingen pga av stora prestandaförluster men om jag förstår det hela rätt så verkar det som att man förbättrat detta i .net. Jag tycker det vore mycket intressant att se på en alternativ arkitektur som klarade av en effektiv databashämtning samt en bra skiktad lösning för skalbarhet. Jag är övertygad om att detta är omöjligt.

/Lukaspojken

LukaspojkenMedlem sedan maj 20011 312 inlägg
#16

-> Gladh
Jag tror du missförstår mig. Jag är inte emot skiktade lösningar. Jag försöker bara se om man kan förbättra arkitekturen kring dessa en aning.

/Lukaspojken

WalkerMedlem sedan okt. 2002188 inlägg
#17

Lukaspojken skrev:

-> OveRRidE
Så här ser det ut idag:

1. Presentationsskikt
2. Fasadskikt
3. Affärs/Logikskikt
4. Dataskikt

Hur skulle datahanteringsskiktet fungera? Använder du något sådant idag? Kan du ge ett exempel på hur du använder det.

Hur ser dina anrop ut idag?

LukaspojkenMedlem sedan maj 20011 312 inlägg
#18

-> Walker
Varför undrar du? I alla fall, här är ett grovt exempel:

Code-behind
dtaItemList = GetDataTable(Item_Id)

BFL
Return GetDataTable(Item_Id)

BLL
Return GetDataTable(Item_Id)

DAL
Dim SelectCommand As IDbCommand = Me.GetCommand("Databas..proc_Storeprocedur")

Me.AddParameter("@Item_Id", Item_Id)

Return Me.CreateDataTable(SelectCommand)

Förresten ett tips kring optimering SQL server. Namnge era procedurer med annat prefix än "sp_". Detta eftersom "sp_" gör att SQL server går först till master-databasen för att se om produceduren är där. Ingen stor prestandavinst men bäckar små :)

/Lukaspojken

WalkerMedlem sedan okt. 2002188 inlägg
#19

Lukaspojken skrev:

-> Walker
Varför undrar du? I alla fall, här är ett grovt exempel:

/Lukaspojken

Bara nyfiken..

Har stött på två olika andra lösningar, en där man har sina save/load/delete metoder i sina affärsobjekt så att det blir

user.load(id) som då öppnar en anslutning och laddar user ojbektet. Vill man sedan ladda en user till så öppnas en connection till, eller den hämtas från poolen och används.. Men sen har jag sett ett annat sätt som jag personligen tycker mer om, vet inte riktigt varför, troligtvis vana bara..

och det innerbär att man har en fasad mot databasen som man jobbar mot.. å då blir det.

uow.Load(typeof(user), id);

det fina med detta tycker jag är att man kan styra när en anslutning öppnas repsektive stängs, vill du hämta fler objekt så..
grov exempel

uow.OpenConnection()
uow.Load(obj1);
uow.Load(obj2);
setUserName(obj2);
uow.Save(obj2);
uow.CloseConnection();

Du använder samma connection hela tiden mao. Detta sker uppe i guiet, eller om du har något annat centralt ställe.. sorry om det blev rörigt men är stressad skall hämta pizza :)

EDIT: load, Load, load, save, Save :r

LukaspojkenMedlem sedan maj 20011 312 inlägg
#20

-> Walker
Det är väldigt intressant det du tar upp och om jag förstår dig rätt så kör du också en skiktad lösning. Finns det några nackdeler med att köra denna lösning istället för den som Gladh och PDahlen förespråkar att man ska använda? Vad säger Gladh och Patrik själva? Det skulle vara intressant att få höra era synpunkter.

Jag tycker att Walker är inne på något som jag gärna skulle vilja spinna vidare på. Kommentarer först :)

141 ms totalt · 3 externa anrop · v20260731065814-full.30151723
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
139 ms — hämta tråd, inlägg och bilagor (db)