En kund har allvarliga prestandaproblem med min applikation (ständiga timeouter och dåliga svarstider) och på fredag skall jag ut till dem och försöka se vad problemet egentligen är. Hårdvarubaserat eller ligger problemet enbart i min applikation...Antal användare är troligen inte fler än 20 samtidigt, och andra kunder med ungefär lika många användare har inte alls samma problem (vilket leder mig till att tro att det i huvudsak är hårdvarubaserat) Hej! Hårdvaran har jag ingen info om ännu mer än att det är 1Gb eller mindre i datorn (de skall uppgradera till 2Gb men om de gör detta från 512 Mb eller 1Gb vet jag inte). På fredag vet jag mer och då kanske jag postar denna info här om inte problemet är löst då. <b>Har dom lika stor datamängd att hantera?</b> Angående låsningarna. Här : http://searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1111751_tax301334,00.html?adg=301324&bucket=ETA kan du hitta ett antal performance counters som är intressanta för MS SQL Server, bla. SQL Server locks som visas som locks/s. Kanontips, skall defintivt köra enligt dessa artiklar och se vad vi kan komma fram till. Har du olika anv.namn per användare i connectionsträngen? det bör man inte ha, då funkar inte connection pooling. <b>"Har du olika anv.namn per användare i connectionsträngen? det bör man inte ha, då funkar inte connection pooling. "</b> Per H >> <b>Problemet är dock den stora tabellen med ärenden som har 20-30 kolumner som nästan samtliga kan sökas på. Jag har en ganska avancerad sökdialog för att söka på alla statusar, datum, fritext etc så det är svårt att sätta index bra på den tabellen. Nånstans går ju gränsen för när man förlorar prestanda på att lägga till fler index antar jag.</b> <B>Det kan ta emot lite men sätt ändå index på allt som går att söka på. Användare är mer känsliga för prestandadippar när det gäller titta än spara. Oftast accepterar man att Spara tar längre tid än att visa listan osv. Databasen kommer att växa lite men som det är i dagsläget med priser på disk behöver du inte bekymra dig om det. Det är ju inte en "very large" database vi pratar om. </B> Ang normalisering: Det scenariot har jag förvisso inte tänkt på men jag kollade igenom tabellen och den består av : Spontan tanke utan att ha läst igenom tråden: Är det inte lämpligt att skapa en view istället för 15 joins? Niklas : Det har inte kommit upp i tråden, men visst har jag en View mot tabellen redan idag. Verkar som en vettig DB. <b>"Om man har flera joins mot olika tabeller och kolumnerna INTE är indexerade Jag funderar på att skriva ett eget program som simulerar flera användare genom att starta flera processer och slumpvis göra läsningar och skrivningar för att kunna på ett vettigt sätt se om indexen gör nytta. Finns det något färdigt program för detta? Vill ju inte lägga tid på detta i onödan om det redan existerar... <b>5) Kan problemet ligga i nätverket (routrar/switchar etc) och i sådana fall hur kollar man det?</b> <b>Jag bör alltså ha index på alla foreign keys? Det har jag definitivt inte idag.</b> <b>Är det så att du inte har indexerat flera av de kolumner som används i JOIN/WHERE är det ganska sannolikt att problemet ligger där. </b> Det finns verktyg för att simulera användare i ett system. Tyvärr kostar de flesta en hel del, men det finns ett verktyg som heter OpenSTA och som är Open Source. Har inget med prestandan att göra men Index är bra, men kan också ta prestanda för att upprätthållas. Hmm...jag har ett gäng användar-ID:n i min ärendetabell som alla pekar på User-tabellen: Jag tycker om datastrukturen. Den är mer dynamisk. Du kan introducera ny roller. Om det _definitivt_ är ett fast antal roller, och alla alltid ska fyllas i är det väl förmodligen så att den ursprungliga versionen är bättre. Ur många andra synvinklar är den andra bättre.Hitta flaskhals-databasprestanda
Förutsättningarna är att det är en .Net applikation (FW 2.0) som jobbar mot Microsoft SQL-Server 2000. Applikationen är flerskiktad och använder typade dataset som databärare ända upp till GUI:t (jo jag vet, kanske inte så bra lösning, men too late...). All dataaccess sker via stored procedures. Programmet är ett ärendehanteringssystem (buggrapportering) och det handlar om < 10.000 ärenden så det är inga enorma mängder data vi pratar om.
Några saker som jag funderar över :
1) Connection pooling - Följande lägger jag till i min connectionsträng förutom själva inloggningsuppgifterna : "connection reset=True;enlist=True;connection timeout=30;Connection LifeTime=30; Min Pool Size = 10; Max Pool Size=80;". Låter dessa inställningar vettiga? Hittade dessa inställningar på nätet så det är ju inte säkert att de passar för min typ av applikation.
2) Tre saker tänkte jag kolla på server, är minnet flaskhalsen, är CPU:n (antal eller hastighet) flaskhalsen samt är hårddisken flaskhalsen. Minnesutnyttjandet och CPU-utnyttjandet är ju relativt lätt att se direkt i TaskManagern, men hur kontrollerar man om hårddisken är flaskhalsen som gör att svarstiderna blir långa?
3) Performance monitor - Jag antar att denna går att använda, men vilka counters bör man titta på och vad är normala värden?
4) Finns det något verktyg i SQL Server 2000 som man kan använda för att hitta dylika problem. Känner till SQL Profilern men att bara få en lista med alla databasanrop ger ju inte direkt någon uppfattning om hur belastad servern är...Däremot tänkte jag ta med mig en sådan lista och köra Index Performance wizard (eller vad den nu heter) på den och se om det finns något att göra där.
5) Kan problemet ligga i nätverket (routrar/switchar etc) och i sådana fall hur kollar man det?
6) Alla förslag på saker jag bör kolla upp är välkomna
Det jag alltså vill komma fram till är om jag skall skriva om applikationen eller om jag skall rekommendera kunden att uppgradera servern. Om det sistnämnda, så vill jag vet om jag skall rekommendera dem mer minne, snabbare hårddiskar, extra CPU:er, eller en helt ny server. Jag har ingen info om deras servers konfiguration idag tyvärr.
[EDIT : Givetvis skall jag även kolla att de har senaste service pack, har kört Windows Update etc]Sv: Hitta flaskhals-databasprestanda
Bara en tanke/fundering i ditt felsökande.
Du skriver: <b>andra kunder med ungefär lika många användare har inte alls samma problem</b>
Har dom lika stor datamängd att hantera?
Kanske har systemet prestanda problem som hör hemma i indexering/SQL frågor.
Eller i applikationens sätt att hantera dina dataset.
Detta visar sig inte förrän en viss datamängd uppnåtts i DBn.
Lycka till med felsökandet.
//HåkanSv:Hitta flaskhals-databasprestanda
Sv:Hitta flaskhals-databasprestanda
Ja just nu har dom det, men det som iofs skiljer sig är att de mycket snabbt har kommit upp i dessa mängder så de registrerar ärenden mer flitigt. Det handlar hos alla kunder om mellan 3-6000 ärenden tror jag, och denna kund ligger visserligen i överkant men det är som sagt andra kunder som också ligger på 5000+ ärenden.
<b>Kanske har systemet prestanda problem som hör hemma i indexering/SQL frågor.</b>
Detta är definivt något som jag har tittat på och kommer att fortsätta titta på. Problemet är att jag inte är speciellt insatt i den här problematiken. Men jag har gjort ett stort antal förbättringar i systemet (index etc) som jag själv kunna mäta (t ex genom att ta tiden på frågor i Query Analyzern) som inte verkar ha förbättrat den upplevda prestandan hos dem.
Men slutsatsen kan mycket väl bli att det är en kombination. Om databasen är dåligt designad (index, normalisering etc) så belastas ju servern hårdare, men samtidigt om hårdvaran är för dålig så lär man ju också få fler låsningar p g a att frågorna inte hinner bli klara innan nästa kommer.
Vilket leder mig till en kompletterande fråga:
<info>Hur identifierar man låsningar i en databas? Med SQL Profilern?</info>Sv: Hitta flaskhals-databasprestanda
I EM gå till MANAGEMENT->CURRENT ACTIVITY.
Där ser du låsningar på processer och objekt.
Kanske skrivs dessa också till loggen (SQL Server Logs).
Vill också påpeka att hur SQL frågan är utformad påverkar prestandan.
(När du ändå kollar över).
Men det är ju klart att hårdvaran kan bli en flaskhals.
Frågan är om du snabbt/enkelt kan jämföra (hårdvarukonfiguration),
mot kunder som det fungerar bättre på.
Kanske den här kunden även har fler databaser som körs rätt flitigt på samma burk.
//HåkanSv: Hitta flaskhals-databasprestanda
Det skulle vara intressant att jämföra den strulande installationen med en installation som fungerar bra men har liknande antal användare.
En annan bra sak att göra är att spara undan en performance baseline (se t.ex. http://searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1111484,00.html) som visar hur systemet beter sig under "normala" omständigheter. Det gör det enklare att hitta problem eftersom de oftast kan identifieras som avvikelser från din baseline.
/AndreasSv:Hitta flaskhals-databasprestanda
Har precis bett en annan kund återkomma med deras hårdvaruspecifikation så att jag har något att jämföra med där också.Sv: Hitta flaskhals-databasprestanda
Connection reset=true? minns inte vad detta är men det låter ju lite "suspekt"... kolla det.
Default connectionstring ÄR vettiga för webbapplikationer. Min connections 10 gör att tio connections konstant är vakna mot db, verkar lite onödigt (men det lär inte sänka en applikation heller).
Det brukar räcka med 2-3 st. Som är default. Alltså jag skulle rekommendera dig att rensa all "kraffs" i connectionstringen och köra default på allt (inte ange mer än nödvändigt där alltså).
Enligt min erfarenhet är prestandaproblem i SQL till 95% pga att det saknas index på frekventa sökvärden, eller att index är felaktiga. Det är mycket möjligt att index tuning wiz kan lösa ditt problem. Tumregel: sätt alltid index på de kolumner som förekommer i WHERE .. , ORDER BY ... samt JOIN .. i SQL! I query analyzer kan du kolla på execution plan. Det du inte vill se där är "table scan".
Det är knappast ett generellt problem att du använder typade Dataset. Förvänta dig inte att du löser prestandaproblem genom att ändra på det (såvida du inte öppnar hela databasen i datasets men det tror jag inte att du gör...) Sv:Hitta flaskhals-databasprestanda
Det är upp till användarna. De kan själva välja i logindialogen om de vill logga in med NT Authentication eller SQL-login, och i det sistnämnda fallet så kan det ju vara så att de skapar personliga konton för varje användare även om jag inte tror att någon gör detta.
<b>Connection reset=true? minns inte vad detta är men det låter ju lite "suspekt"... kolla det.</b>
Will do...
<b>Enligt min erfarenhet är prestandaproblem i SQL till 95% pga att det saknas index på frekventa sökvärden, eller att index är felaktiga. Det är mycket möjligt att index tuning wiz kan lösa ditt problem. Tumregel: sätt alltid index på de kolumner som förekommer i WHERE .. , ORDER BY ... samt JOIN .. i SQL! I query analyzer kan du kolla på execution plan. Det du inte vill se där är "table scan". </b>
Jag tror att jag har index på alla WHERE/ORDER BY/JOIN där det finns relevanta datamängder, men jag kommer säkert att hitta en del när jag fått tillgång till kundens Profiler-resultat. Så då blir det till att köra Index tuning wiz.
Problemet är dock den stora tabellen med ärenden som har 20-30 kolumner som nästan samtliga kan sökas på. Jag har en ganska avancerad sökdialog för att söka på alla statusar, datum, fritext etc så det är svårt att sätta index bra på den tabellen. Nånstans går ju gränsen för när man förlorar prestanda på att lägga till fler index antar jag.
F ö är det en WinForm-applikation. Datalagret är dock skrivet så att anslutningarna bara är öppna under en kort stund, så poolingen borde fortfarande vara relevant.
<b>Det är knappast ett generellt problem att du använder typade Dataset. Förvänta dig inte att du löser prestandaproblem genom att ändra på det (såvida du inte öppnar hela databasen i datasets men det tror jag inte att du gör...) </b>
Nej precis, jag planerar visserligen att skriva om businesslagret så småningom, men knappast av prestandaskäl.Sv: Hitta flaskhals-databasprestanda
Det kan ta emot lite men sätt ändå index på allt som går att söka på. Användare är mer känsliga för prestandadippar när det gäller titta än spara. Oftast accepterar man att Spara tar längre tid än att visa listan osv. Databasen kommer att växa lite men som det är i dagsläget med priser på disk behöver du inte bekymra dig om det. Det är ju inte en "very large" database vi pratar om. Och det där med ~25 kolumner låter lite sådär. Du kan eventuellt vinna prestanda med normalisering men det där är en avvägning, inte alltid som det hjälper heller. Vad du än gör.. testa först :)
Aha, det är Win forms.. då ska du se upp med poolingen. När du säger Min Poolsize=10 innebär det att varje windowsklient vid första anrop till databasen kommer att hysta upp 10 st beständiga connections mot databasen. Kolla i enterprise managern! Jag tror inte att problemet ligger där egentligen men det ser ju inte bra ut :) sätt min pool size till 1, Max vågar jag inte säga.. under 10 bör det säkert vara.. Googla det :)
(obs: för ASP.NET gäller andra rekommendationer, där är det bra att ha ett gäng connections mot databasen eftersom de återanvänds mellan olika requests.. det är ju alltid iis-processen som connectar mot SQL där och då är det grymt bra med en pool med några objekt som återanvänds)Sv:Hitta flaskhals-databasprestanda
Jag får testa detta, det är dock svårt att mäta prestandan i min egna miljö med en användare (jag).
<B>Och det där med ~25 kolumner låter lite sådär. Du kan eventuellt vinna prestanda med normalisering men det där är en avvägning, inte alltid som det hjälper heller. Vad du än gör.. testa först :)</B>
Jag är ingen expert på normalisering, men jag tror att den är korrekt normaliserad.
<b>Aha, det är Win forms.. då ska du se upp med poolingen. När du säger Min Poolsize=10 innebär det att varje windowsklient vid första anrop till databasen kommer att hysta upp 10 st beständiga connections mot databasen. Kolla i enterprise managern! Jag tror inte att problemet ligger där egentligen men det ser ju inte bra ut :) sätt min pool size till 1, Max vågar jag inte säga.. under 10 bör det säkert vara.. Googla det :)</b>
Intressant, skall testa det.Sv: Hitta flaskhals-databasprestanda
Två scenarion:
A) AdressBok.ORT varchar(30) indexerad
B) AdressBok.OrtID int(4) indexerad
OrtID är foreign key och pekar på Ort.OrtID i tabellen Ort som också innehåller Ort.OrtNamn
A är inte normaliserad. B är normaliserad. (3 NF).
I case A kostar det mer att söka och att skapa nya poster eftersom
det är en varchar(30) som ska behandlas. (sätta in i tabell + uppdatera index)
I case B kostar det mindre eftersom det bara är en int (4 bytes) som ska behandlas.
Dock ska man tänka på att om man har väldigt många foreign keys i en tabell,
då krävs många JOINs och det kostar också. Och det blir förstås mer komplicerad SQL att skriva.
Så det är inte alltid bra att normalisera allt.Sv:Hitta flaskhals-databasprestanda
primary key
ett gäng flaggor (bit)
ett gäng datumfält
ett gäng users (foreign key till User-tabellen, ca 5 st)
ett gäng övriga foreign keys till olika statustabeller (runt 10 stycken)
5 fria textfält som inte har en begränsad mängd värden (som ditt exempel med Ort)
Så jag tror inte det går att hitta några fler normaliseringar här.
Men jag har med andra ord ca 15 joins att göra om jag skall ha upp alla värden. Är detta tokmycket?Sv: Hitta flaskhals-databasprestanda
Då har ju databasen åtminstone en chans att cacha det...Sv:Hitta flaskhals-databasprestanda
Sv: Hitta flaskhals-databasprestanda
15 joins ska väl gå bra.
Det är i överkant men jag ser inte att det skulle sega ner så mycket.
Om man har flera joins mot olika tabeller och kolumnerna INTE är indexerade
så kan det bli väldigt dyrt. Dubbelkolla att du har lämpliga index.
Analysera frågorna vilket du redan har varit inne på att göra.
Ett annat test du kan göra: ta en backup på databasen och gör restore
hemma och se vad du får för svarstider där. Sv:Hitta flaskhals-databasprestanda
så kan det bli väldigt dyrt. Dubbelkolla att du har lämpliga index."</b>
Jag bör alltså ha index på alla foreign keys? Det har jag definitivt inte idag.
Idag har jag för övrigt varit ute hos kund och vi har lyckats utesluta att problemet är hårdvarubaserat, i alla fall om vi tolkat alla performance counters rätt.
Vi gjorde ett test där en användare ställde en fråga mot tabellen Task som är den centrala tabellen med ca 8000 ärenden i. Person A läste upp ca 500 ärenden av dessa 8000, vilket hos mig inte ens tar en sekund, men hos dem tog det nog 10 sekunder, under tiden läste person B upp 6000 kunder ur tabellen kund och detta gick blixtsnabbt, trots att Person A satt och väntade. Det tolkar jag som att problemet helt och hållet ligger i ärendetabellen (Task) och att läsningar/skrivningar låser varandra där. Ärendetabellen är ju väldigt central i denna applikation och det kan vara 20 personer som läser och skriver "samtidigt" ur denna tabell.
Vad har ni för rekommendationer om att ändra Isolation Level till Read Uncommited? Detta skall ju tydligen göra att läsningar inte blir låsta av pågående skrivningar. Detta kan förstås leda till consistensy-problem men hur mycket problem kan det leda till?
Andra tankar om hur man går vidare med detta?Sv: Hitta flaskhals-databasprestanda
Det jag vill att programmet skall kunna är :
1) Lägga upp ett antal anrop till SP:s med lämpliga parametrar för varje SP
2) Lägga upp ett "schema" för hur ofta dessa skall anropas (t ex var x:te sekund, slumpvis,...)
3) Hur många processer (simulerade användare) som skall startas och anropa SP:s enligt ovanSv:Hitta flaskhals-databasprestanda
Jag har haft något som liknar detta.
När det gällde en mindre databas i Access med betydligt mindre data hade jag ett liknande problem, men med betydligt färre användare än vad du verkar ha. Då var det fel satt i switcharna så inställningarna för switchen var olika gentemot inställningarna på klienten, avseende full/half duplex.
Alltså - tips! - kolla inställningarna i switchen och på klienternas nätkort. Dessa inställningar skall vara samma - det är det viktiga! - helst Auto, men bara de är samma så kan det hjälpa dig avsevärt.
/ PerSv: Hitta flaskhals-databasprestanda
Det är en bra praktik att ha det, men nödvändigheten beror lite på hur SQL-frågorna ser ut samt hur mycket data det är..
<b>
Andra tankar om hur man går vidare med detta?</b>
Är det så att du inte har indexerat flera av de kolumner som används i JOIN/WHERE är det ganska sannolikt att problemet ligger där.
Analysera frågorna i Query Analyzern och leta efter 'table scan', dessa vill du undvika!
(show execution plan, CTRL+K)
Körde du Index tuning wizard?Sv:Hitta flaskhals-databasprestanda
Snarare ingen :-) Detta blir det första jag testar när jag är klar med min stresstest-applikation...
<b>Körde du Index tuning wizard?</b>
Har testkört en gång men jag tror att jag fick för LITE data p g a att jag fick för MYCKET data. Med andra ord, vi la på rätt många events, inklusive alla låsningar så på bara en timme fick vi 600MB med data. Det hade antagligen varit bättre just för Tuning Wizard att få ett par dagars resultat från de event som innehåller SP/SQL-anrop och ignorera allt annat.
Resultatet blev att jag fick ett par index över flera kolumner som ganska väl stämmer överens med de få läsningar (urval) vi gjorde under den tid som profilern loggade. Jag är inte övertygad om att detta är relevanta index...jag skall be dom göra om loggningen under en längre tid med endast de kolumner som dokumentationen rekommenderar (RPC:Completed, SQL:BatchCompleted).
Den ville också lägga på en massa CREATE STATISTICS, detta måste jag uppenbarligen läsa på...också...*suck* det är inte helt lätt det här :-)Sv:Hitta flaskhals-databasprestanda
Har bara kört det som komplement till Loadrunner från Mercury när vi var tvungna att simulera 10000 samtidiga användare i ett system och då kommunicerade vi via en webbserver över HTTP. Vet tyvärr inte om det går att implementera med WinForms.
På servern kan du förutom att mäta cpu, disk m.m. även kolla current connections. Se till att de inte flyger iväg allt för mycket. Gör detta genom perfmon eller med netstat -an (om du kan skilja på klienter och andra genom ip adresserna).
Mvh DavidSv: Hitta flaskhals-databasprestanda
>ett gäng users (foreign key till User-tabellen, ca 5 st)
Låter som en många till många relation och kan normaliseras till en kopplingstabell.Sv: Hitta flaskhals-databasprestanda
Kolla vad det är för procent på <b>FIll factor</b> på indexen.
Bör vara 0.
Välj Design table-->Manage Indexes/Keys på den tabell du vill kolla.
I tabben Indexes /Keys ser du vilken <b>Fill factor</b> du har för indexen.
Kan vara ett långskott, men går snabbt att kolla och isåfall åtgärda.
//HåkanSv:Hitta flaskhals-databasprestanda
Tabell Task:
=========
ResponsibleID
RegisteredByID
AssignedToID
AssignedByID
etc
Tabell User:
=========
ID
Name
Borde detta göras om på så sätt att ovanstående användarrelaterade fält tas bort från ärendetabellen (Task) och ersättas med :
Tabell Rel_TaskUser:
===============
TaskID
UserID
Type -- 0=Responsible, 1=RegisteredBy,2=AssignedTo ...
Tabell User:
=========
ID
Name
Är det så du menar? Det känns som att detta inte bara komplicerar datamodellen utan dessutom tvingar mig att använda två joins per koppling i st f tidigare en join. Är det något jag missar här?Sv: Hitta flaskhals-databasprestanda
Jag tror dessutom att antalet index bör minska med den lösningen.Sv: Hitta flaskhals-databasprestanda