Det sägs ju att man ska hålla connection till databasen öppen så kort tid som möjligt. Men till hur hög grad gäller detta? Det är en extremt dålig lösning. Du ska hålla öppen anslutningen så länge du behöver, sedan stänga ner den. I regel gäller det att öppna den första gången du behöver det och stänga efter sista frågan du kör. "Varje gång MyItem.load() körs görs ett databasanrop samt en del andra c# beräkningar. " Jag gör inte så hemskt mycket i item.load() Om man gör fristående applikationer (inte webb) och kommunicerar med en extern databas så finns det väl knappast någon connection pool att ta av internt? Varifrån kommer dina klasser? Hur har du sparat dina variabler? "Om man gör fristående applikationer (inte webb) och kommunicerar med en extern databas så finns det väl knappast någon connection pool att ta av internt?" "men i mitt tycke är det enbart skäl att stänga en anslutning om bearbetningen av data tar lite längre tid." Det jag menade med att stänga anslutningen innan man gör tyngre bearbetning var i princip "nu vet jag att dessa beräkningar/annat tar si och så länge". Självklart kan man inte börja gå ner på millisekundnivå.Öppna/stänga connection?
Jag har en ASP.NET C# applikation med flera klasser ett scenario är till exempel:
1. Hämta en lista med ID från databasen.
2. Loopa igenom denna lista och skapa klasser
{
item = new MyItem();
item.load(id);
this.add(item);
}
Varje gång MyItem.load() körs görs ett databasanrop samt en del andra c# beräkningar.
Just nu gör jag så att jag stänger och öppnar connection varje gång ett item laddas, är det en dålig lösning?Sv: Öppna/stänga connection?
Sen är det väldigt ineffektivt att köra flera frågor, skriv om koden så att du gör så få frågor som möjligt för att ladda in data.
Det är i regel bättre att ladda in lite för mycket data än för lite, eftersom varje SQL sats måste bearbetas och tolkas innan den kan köras etc.Sv: Öppna/stänga connection?
Svårt att svara på då man inte vet vad som händer i beräkningarna och hur ditt program ser ut i övrigt. Jag är dock inte alls lika säker på att det är en sådan dålig lösning som Thomas vill få det till.
Utgångspunkt är alltid att du skall
Öppna - Hämta - Stäng - bearbeta - öppna - hämta - stäng - bearbeta. Öppna - Hämta - stäng - bearbeta.
Istället för
Öppna - hämta - bearbeta - hämta - bearbeta - hämta - bearbeta - stäng.
I 99% av fallen är detta en sämre lösning än den första och allt beror på att du har din connectionpool som hanterar överlämnandet av öppna kopplingar till dig när du behöver dem. Eftersom det kostar väldigt lite i prestanda att hämta en koppling från poolen, men otrligt mycket att skapa en ny till databasen så är det viktigt att man inte har fler kopplingar öppna samtidigt än vad man har i poolen. Genom att då ha varje koppling öppen så kort tid som möjligt så minimerar du risken att behöva öppna en ny koppling till databasen. Skräckexempel är websidor som öppnar en databasanslutning i sitt Page_Load() event och stänger dessa i Page_UnLoad(), det är verkligen en NO NO situation.
Det man måste tänkta på är att man inte är själv om resurserna i datorn eller i databasen och att därför är det heller ingen lösning att istället bara sätta sin connectionpool till att hålla 500 öppna kopplingar för att slippa problemet med att dessa skall ta slut.
IPrincip så skall du alltid välja lösning 1 om du vill bygga system som är skalbara, även om det kanske kostar lite i prestanda för varje anrop så tjänar du igen det när du får många anrop.
Sedan har Thomas helt rätt i att det är bättre att hämta all data med ett anrop än att göra många små, men det kanske inte är möjligt och så fall får man ta en prestandahit för att få den funktionallitet som man efterfrågar.
Och om du tänker göra om det till följande kod:
<code>
- Öppna databaskopplingen
1. Hämta en lista med ID från databasen.
2. Loopa igenom denna lista och skapa klasser
{
item = new MyItem();
item.load(id);
this.add(item);
}
- Stänga databaskopplingen
</code>
Så är min rekomendation att detta är en sämre lösning även om du inte gör så mycket beräkningar i item.load(id) och ju mer du gör där eller i konstruktorn för MyItem() ju sämre lösning blir det.
- MSv:Öppna/stänga connection?
Jag gör bara ett databasanrop som selectar några variabler som jag sparar i klassen.
Visserligen skulle jag kunna ha en metod i stil med item.build(string itemName, DateTime itemCreated, etc..)
Men att ha en universal load-klass känns bättre om jag t.ex. ska lägga till en variabel i framtiden.
Men kanske finns någon lösning jag inte tänkt på?Sv:Öppna/stänga connection?
För den "lokala" prestandan så måste ju en enda connection vara betydligt bättre?
Och då uppstår ju problemet när många kommunicerar samtidigt, och då slöas databasen ner, men det känns vettigare med en stor paus än att varje enskilt anrop riskerar att vänta.
Hur som helst.
<b>>Utgångspunkt är alltid att du skall
Öppna - Hämta - Stäng - bearbeta - öppna - hämta - stäng - bearbeta. Öppna - Hämta - stäng - bearbeta.
Istället för
Öppna - hämta - bearbeta - hämta - bearbeta - hämta - bearbeta - stäng. </b>
Och så finns ju en tredje variant om man inte är beroende av tidigare bearbetningar för nästa hämtning (vilket är sant jävligt ofta):
Öppna - hämta - hämta - hämta - stäng - bearbeta - bearbeta - bearbeta.Sv: Öppna/stänga connection?
Det du i många fall kan göra är att ladda in alla variabler för alla klasser i minnet första gången du kör item.load() och därefter laddar du in dem från minnet till klasserna.
I princip är det säkert bra att ha någon form av Data Mapper klass som gör detta och lagrar dem internt och returnerar dessa om de finns i minnet, annars laddar den dem från databasen och returnerar dem därefter.
Det kan hända att det i vissa fall är bättre att öppna - ladda - stänga databasanslutningen för att frigöra den till andra processer, men i mitt tycke är det enbart skäl att stänga en anslutning om bearbetningen av data tar lite längre tid. Det bästa är att ladda in all data du kan tänkas behöva i så få databasanrop som möjligt och därefter stänga anslutningen.Sv: Öppna/stänga connection?
Jodå det finns en pool men den används ju inte på det sättet som den är tänk till eftersom det bara finns en användare hela tiden.
Det stämmer att om man kör en användare system så behöver man knappast tänka på detta problem, eftersom prestandan knappast är ett problem i detta fall. Men problemet att det är svårt att lära gamla hundar att sitta, och om man utvecklar enanvändarsystem på detta sättet så kommer man göra likadant när man väl flyttas över och börjar utveckla fleranvända system.
Och den lilla stund det tar att hämta en connection från poolen (den är ju redan öppen mot databasen så det tar inte många ns) är helt klart värd i ett en användarsystem, för att man skall "göra rätt" när man väl hamlar som utvecklar i fler användar system.
Det "prestanda" problem som finns med att hämta en connection från poolen är så försumbar i alla andra flaskhalsar som programmen har så det hade varit bättre att lägga krutet där istället.
"Öppna - hämta - hämta - hämta - stäng - bearbeta - bearbeta - bearbeta."
Det skulle vara bättre med Öppna - HÄMTA - stäng - bearbeta - bearbeta - bearbeta", om man nu kan lösa det på det sättet om man inte är beroende av tidigare data. Alltså endast ett anrop som hämtar all data.
- MSv:Öppna/stänga connection?
Problemet är att du inte har en aning om hur länge bearbetingen tar, även om du bara har ett enda processoranrop så kan det tar sekunder (och lite överdrivet) mellan det att du öppnar din databas och du stänger den, och det finns ingen möjlighet för dig att "styra över det", om du inte går in och börjar priortera dina trådar, vilket du knappast skall göra. Så generellt gäller att så få processor anrop som möjligt mellan öppnandet och stängande av din databaskoppling, det ger dig nämligen så litet fönster som möjligt för OS att skifta iväg tråden precis när du har din koppling öppen till databasen.
Jag har skrivit om detta på webforum ett antal gånger, men lyckas aldrig hitta de artiklarna igen :(. Men jag hittade en gammal tråd från 2007 där vi fick svar på att servern också har en connectionpool som den använder sig av så länge din koppling är öppen. Så om du har ett "en användarsystem" men det används av 1000 användare så betyder det att om alla din 1000 användare öppnar kopplingen mot databasen samtidigt och stänger den samtidigt så har du alltså 1000 öppna kopplingar på databasen, men om du använder dig av poolen och stänger den emellan din frågor så kan servern återanvända din koppling till en annan klient och du där mer frigör resurser till servern. Så rekomendationerna är att alltid använda sig av connectionpoolen och göra så lite som möjligt så länge kopplingen är öppen även om man bara bygger enanvändar system, och skulle det vara så att det bara finns en klient av din programvara så finns det garanterat andra systemet som vill använda databasen samtidigt som dig.
http://www.webforum.nu/showthread.php?t=161925&page=2&highlight=connection+pool
- MSv: Öppna/stänga connection?
Men det bästa är ju som tidigare nämnt "Öppna - Hämta - Stäng - Bearbeta - Öppna - Hämta/Skriva - Stäng...".