SQL Server på svenska


Kolumntyper är viktiga om en tabell får många anrop - 2020-05-27

Vi har tidigare tittat på 2 olika scenarion när det är extra viktigt att optimera sin tabell, när man har många rader i den eller den har många relationer till andra tabeller. Men det finns ett tredje som troligen är ett av det viktigaste, att optimera tabeller som anropas ofta. Orsaken till det är inte att spara plats utan att minska belastningen på servern. Låt oss titta på en optimerad version av vårt tidigare exempel.

Som vi kan se här så har jag optimerat tabellen för Products, där jag valt mer effektiva kolumntyper. Orsaken till det är att jag antar att tabellen Products kommer anropas oftare än tabellen Orders. Om vi tänker oss att vår databas är kopplad till en webb-shop så är det väldigt troligt att betydligt fler kommer gå in och titta på olika produkter och läsa om dom än antalet som faktiskt kommer lägga en order. I detta fallet gör jag ett antagande om hur databasen kommer användas, i verkligheten måste man ha någon typ av kontroll/övervakning av systemet för att faktiskt veta vilka tabeller som används mest.

En viktig slutsats från de senaste inläggen är att man gör bäst i att optimera alla tabeller i en databas. Det är svårt i början av utvecklingen av ett nytt system att veta om vilka tabeller som kommer ha många anrop, många rader eller många relationer. Därför bör man lika väl optimera kolumntyperna på en gång. Det är betydligt enklare att göra det tidigt i utvecklingen än längre fram.

En tabell med relationer bör optimeras - 2020-05-20

I förra inlägget tittade vi på att det är viktigt med att optimera tabeller som har många rader i sig, för att spara plats i databasen. Nu ska vi titta på nästa steg, att det även är viktigt att optimera tabeller som har många relationer till andra tabeller. Låt oss tittar vidare på samma exempel som vi haft tidigare, men där vi nu har lagt till en ny kolumn för en foreign key från tabellen med ordrar till tabellen med produkter.

Som vi tydligt nu kan se så har vårt dåliga val av kolumntyp i en tabell med få rader orsakat att vår tabell med många rader också har en väldigt dålig kolumntyp. Detta är något som är typiskt för databaser, börjar man välja dåliga kolumntyper så blir man tvungen att återanvända dåliga kolumntyper längre fram i designen. Det rätta valet här vore självklart att välja en kolumntyp som är betydligt bättre för syftet, ungefär som bilden här under.

Från dagens exempel så ser vi tydligt att det är viktigt att tänka på kolumntyperna även för tabeller som vi förväntar oss ha få rader i sig. Framförallt om vi tror eller vet att denna tabellen kommer få relationer till andra tabeller med betydligt fler rader i sig.

Fler rader gör optimering viktigare. - 2020-05-15

I förra inlägget tittade vi på att det kunde göra stor skillnad vilka kolumntyper man valde. I det exemplet vi tittade på kunde man spara 73 % av platsen genom att välja mer effektiva kolumntyper. Men då kommer frågan, när är det viktigt att tänka på detta?

Det finns egentligen 3 olika tillfällen när det är viktigt att ta hänsyn till kolumnernas storlek. Det första är när man gör väldigt många anrop till tabellen, och det andra är när man har väldigt många rader i tabellen, samt det tredje är när en tabell har väldigt många relationer till andra tabeller. Låt oss börja med att titta på det enklare scenariot, när man har många rader i tabellen.

Här under har vi en bild på 2 tabeller. Här har jag valt att optimera den ena tabellen men inte den andra. Och då valde jag att optimera tabellen som jag förväntar mig ha många fler rader. (Självklart hade det varit bäst om jag hade optimerat bägge.)

I tabellen ovan förväntar vi oss betydligt fler rader i tabellen för ordrer än produkter, startar man en butik hoppas man ju att man säljer varje typ av vara mer än en gång. Det finns många butiker som har några hundra olika produkter men hundratusentals ordrar, och då är det viktigare att optimera ordrarna än att optimera produkterna. Huvudpoängen är alltså, desto fler rader man förväntar sig desto viktigare är det med kolumnoptimering.

Spara plats med olika datatyper gör skillnad. - 2020-05-06

Jag har länge pratat om för och nackdelar mellan olika datatyper i ens tabeller. Och en av sakerna som jag nämnt många gånger är om en datatyp tar upp mycket eller lite plats i databasen. Nu tycker jag det är dags att kolla på vilken skillnad det kan göra. Låt oss skapa 2 hittepå-tabeller. En tabell där jag har optimerat för att minska utrymmet och ett där jag inte gjort det. Du kan se de 2 tabellerna här under.

Förhoppningsvis märker ni direkt flera dåliga designval här, men låt oss titta vidare på vilken skillnad vi får. I nästa steg så stoppar vi in 5 miljoner rader i varje tabell. (Det tog mig 40 minuter att stoppa in raderna.)

Som ni märker så får vi plats med samma information i bägge alternativen, trots att den mindre tabellen har mindre datatyper. Vi kan se att allt kommer med och får plats här under. (Om du är osäker på skillnaden mellan de olika kolumntyperna så har jag tidigare inlägg i denna bloggserie som går igenom varje datatyp och jag kommer inte upprepa mig här.)

Här under så kan du se hur mycket plats de 2 tabellerna tar upp. Den mindre tabellen tar upp ungefär 400 mb mindre, eller 73 % mindre utrymme. För stora databaser så blir detta en väldigt stor skillnad. I nästa inlägg så ska vi fortsätta med att titta på när det är viktigt och inte lika viktigt att tänka såhär.

6 månader! - 2020-05-03

Då har det gått ett halvår (6 månader och 1 dag) sedan jag startade bloggen. Aktiviteten har gått upp och ner under den perioden, och just nu befinner jag mig i en svacka. Den senaste månaden har jag endast publicerat 3 inlägg, långt under mitt mål om 8. Orsaken till detta är att jag dels har en hel del att göra med mitt hus just nu och dels att det finns så himla många andra som ger ut gratismaterial nu i coronatider. Jag ägnar alltså min tid åt att lära mig mer om SQL Server snarare än att lära ut för närvarande. Exempelvis så ska jag följa ett webinar nu på tisdag, länk här under.

https://www.quest.com/event/quest-database-training-days8142529/

Eftersom mitt liv för övrigt lär fortsätta som under den senaste tiden så är mitt nya mål att jag ska publicera 1 inlägg varje vecka. Lite lägre takt än tidigare, och det lär fortsätta så fram tills efter semestern. Men och andra sidan kan ni hoppas på att inläggen blir allt med avancerade i takt med att tiden går.

Identity-kolumn - 2020-04-29

Ett av mina favoritsätt att skapa en primary key är genom en identity-kolumn. På detta sätt så garanterar man att man har unika värden för varje rad. Jag har använt det förut och jag kommer göra det många gånger igen. Låt oss titta på hur det kan fungera att skapa en.

Som ni ser så behöver man inte börja vid identity(1,1), även om det är det normala och det jag huvudsakligen använder. Det känns så tydligt att veta vad som är första raden och den andra osv.

En orsak till att jag förespråkar användandet av identity-kolumn som en primary key istället för något genererat i applikationen är att det är säkrare. Applikationen kan startas om, den kan krascha, man kan köra applikationen på flera servrar osv. Om databasen är ansvarig för att ens primary key är unik så minskar man risken för att något skulle bli fel. Dessutom är det ett betydligt effektivare sätt att ha en unik nyckel än att använda sig av en GUID, som jag ofta ser. Titta bara på bilden här under.

Som ni ser så är en identity-kolumn (om den är en int) 4 gånger så effektiv när det kommer till lagringsutrymme. (Och även om det skulle behöva vara en bigint så är den dubbelt så effektiv.) Förutom detta så finns det även fler fördelar som jag i senare delar kommer ta upp, vilket främst uppkommer när man börjar ha riktig data i tabellen eller när man har många tabeller ihop. Det jag kan runda av med är att jag personligen tycker identity är en bra funktion för att skapa en primary key till varje tabell.

Primary key för flera kolumner - 2020-04-14

En primary key behöver inte vara en ensam kolumn, man kan ha en primary key som är sammansatt av flera kolumner. Detta möjliggör att man inte längre får kravet att kolumnen måste vara unik, utan det är kombinationen av värden som måste vara unik. Det finns flera olika tänkbara scenarion när det kan komma till pass att använda sig av flera kolumner i en primary key, nedan kan du se hur man skapar det för 2 kolumner i en tabell.

Som ni ser går det bra att då ha dubbla värden i kolumnerna nu när primary key gäller för 2 kolumner, men kombinationen av dom måste vara unik. Går man in i SSMS (SQL Server Management Studio, verktyget jag använder hela tiden) och tittar på tabellen så kan man se att man nu har en primary key för 2 kolumner. Se bilden nedan.

De flesta primary key jag har i mina databaser är för en enskild kolumn. Men det är viktigt att känna till möjligheten att ha flera kolumner för det händer, jag har vid flera tillfällen lagt till en primary key för flera kolumner. Ska jag gissa, utan någon som helst statistik, så tror jag att 1 av 20 gånger så använder jag en primary key för 2 eller fler kolumner.

Primary key i din tabell - 2020-04-08

När man skapar en tabell i SQL Server så kan man antingen ha en primary key eller inte. Skillnaden på om man har det eller inte är flera. En viktig skillnad är att det i så fall finns en nyckel till varje rad i tabellen, värdet i tabellens primary key är unikt och kan ensamt identifiera en rad. Det är själva definitionen av en primary key. Det enklaste sättet att skapa en primary key är på följande sätt.

Som ni ser så är det enkelt att lägga till en primary key när man skapar en tabell. Men det går också att göra det på en redan existerande tabell med rader i sig, som ni kan se här under. Dock måste man först göra om kolumnen till not null eftersom en primary key inte kan innehålla null-värden.

Om man skulle ha en massa null-värden i kolumnen så skulle det inte vara lika enkelt att lägga till, eftersom man måste i så fall uppdatera värdena i kolumnen. Värdena i kolumnen måste även vara unika för att det ska gå att lägga till en primary key. I ett mer realistiskt scenario så behöver man troligen lägga till en ny kolumn för att lägga till en primary key. Här under ser vi ett enkelt sätt att lägga till en sådan kolumn.

5 månader! - 2020-04-02

Då har det nu gått 5 månader sedan jag startade bloggen, och vi befinner oss i ett helt annat läge nu än tidigare. Aldrig tidigare har digitalt lärande varit så viktigt som det är just nu, eftersom alla fysiska utbildningstillfällen är avbokade i coronakrisens spår. (Vilket förvisso inte är ett så stort problem i jämförelse med alla andra problem.) Men det kan vara ett problem, det kan vara ett stort problem för din fortbildning och därigenom din framtida karriär. (Det påverkar även dina möjligheter att lösa dagens och morgondagens utmaningar på jobbet.)

För att hjälpa dig med ditt digitala lärande så har jag flera gånger den senaste tiden lagt upp rekommendationer till olika gratiskurser/webinars. Jag kommer fortsätta med detta parallellt med att jag kommer skriva egna blogginlägg med matnyttig information. Därför rekommenderar jag dig att hålla dig uppdaterad och fortsätta läsa bloggen. Vill du vara säker på att inte missa några förslag eller inlägg? I så fall kan du registrera dig här på bloggen och välja att få ett mejl varje gång ett nytt inlägg läggs upp.

Under den gångna månaden så har jag lagt upp 6 matnyttiga inlägg eller tips. Det är lite mindre än mitt mål, med 8 stycken per månad, men ändå inom rimlighetens gränser. Under den kommande månaden så får vi se om jag kommer upp i 8 stycken eller ej. Det beror nog väldigt mycket på min arbetsbörda i övrigt, och nu lever vi igenom ganska osäkra tider, så inga löften. Ta hand om dig så kommer jag troligen ganska snart ut med något mer matnyttigt.

Ännu mer gratismaterial där ute! - 2020-03-31

Nu kommer ännu ett tips på gratis fortbildning. Detta är kanonbra tider för oss att fortbilda oss själva och bli ännu bättre på databaser och SQL server. Jag kommer definitivt vara på så många av dessa webinars jag bara kan. Och eftersom jag själv tänkte lära mig nya saker där så rekommenderar jag även dig att lyssna. Ibland lär man sig mycket nytt, ibland lär man sig mindre men då är det ofta en bra repetition av gammal kunskap.

https://www.quest.com/event/quest-database-training-days8142529/

Kom ihåg att det är ett mycket generöst erbjudande att få gå på live-kurser såhär helt gratis. Många av dessa brukar ta bra betalt för att tala och utbilda, därför rekommenderar jag verkligen folk att passa på att nu ta del av dessa helt gratis!

Datetimeoffset och varför du bör undvika den - 2020-03-30

Det finns an helt annan kolumntyp än dom jag pratat om tidigare som också berör tider, nämligen datetimeoffset. Denna typen är precis som en vanlig datetime2 fast man kan även spara tidszonen i den. Alltså om klockslaget är +1 timme eller +8 timmar jämfört med GMT. Precis som för en vanlig datetime2 kan man ange längden, och desto längre desto mer plats tar den upp. Datetimeoffset tar upp lika mycket plats som en datetime2 men 2 extra bitgrupper (bytes), för att kunna spara tidszonen vilket ni ser på bilden här under.

Personligen skulle jag avråda från att använda just en datetimeoffset. Jag förespråkar alltid att man använder datetime2 och enbart sparar tider i UTC, och vill någon användare se någon annan tid så löses det i front-end delen och inte i databasen. Sen kan jag förstå att det finns system där ute som redan kör med att tidszonen sparas i databasen och i så fall har jag förståelse för att man inte ändrar på saker och ting. Jag hade dock skrivit upp det på listan över saker som borde ses över och åtgärdas när tid ges.

(För er som inte redan vet.) Varför bör man inte ha tider sparade med tidszonen? Jo, eftersom det finns så många olika specialfall att ta hänsyn till. Om det står att man har tidszonen +1, hur tar du då hänsyn till sommar/normaltid? Det är ju inte så enkelt som att alla länder kör med samma tidssystem, hur har du tänkt att ta höjd för det? Nedan finns en länk till wikipedia över hur olika länder tänker olika, dels med om man har sommartid eller inte, och när man i så fall har det. Alltså kan +01:00 ibland vara +02:00, men inte alltid och inte för alla länder. Hur ser din strategi för det? Eller kör du enbart med normaltid? Det blir med andra ord väldigt fort rörigt, därför avråder jag folk från att använda sig av tidszoner i databaser. (För kom ihåg, det räcker med att 1 utvecklare missar hur ni gör för att allt ska bli kaos om ni inte har som policy att köra med UTC.)

https://en.wikipedia.org/wiki/Daylight_saving_time_by_country

Uppdatering!

Här kommer en helt lysande video som går igenom en lång rad av alla problem med att försöka lösa allt med tidszoner och liknande problem själv. Absolut sevärd. (Den är dock på engelska.)

https://www.youtube.com/watch?v=-5wpm-gesOY

Ännu en gratis kurs! - 2020-03-19

Jepp, det är lite galna tider just nu. (Med tänke på coronaviruset och allt.) Själv försöker jag blanda alla mina vanliga uppgifter med att lära mig lite extra online. Så gör troligen även du, eftersom du trots allt hänger här. Nu har Brent Ozar slängt upp ännu en kurs gratis under Mars månad, länk nedanför.

https://www.brentozar.com/archive/2020/03/free-fundamentals-of-query-tuning-week-part-1-building-a-query-plan/

Jag hoppas att jag lite senare i månaden får mer tid att skicka upp lite fler inlägg, under tiden hoppas jag du sköter om dig och inte glömmer att tvätta händerna.

När (date och time) är bättre än datetime2! - 2020-03-13

Så, i förra inlägget så såg vi att man antingen kan ha en datetime2 eller dela upp den i en date och en time. När det kom till diskutrymme så är det alltid bäst att köra på en datetime2. Men när det kommer till databaser och SQL Server så finns det fler saker att ta höjd för. Exempelvis prestandan, och nu ska jag visa er ett exempel när det kan vara bra att dela upp den.

Och tillfället som det är bra att dela upp en datetime2 är när man ska göra filtreringar och analyser utifrån enbart en del i taget. (Exempelvis när man bygger ett data warehouse.) Tänk er exempelvis att man har någon typ av försäljning och man vill snabbt se försäljningen under vissa timmar på dygnet, i fallet nedan vill man se försäljningen mellan 10 och 12 på förmiddagen.

Fördelen i detta exempel är att man kan sätta ett index på Dat3 för att öka hastigheten när man har en tabell med väldigt många rader. Man slipper även att göra någon typ av cast eller liknande. Men dessa fördelar finns enbart om man har just detta behovet. Man måste helt enkelt anpassa databasen utifrån vilka behov systemet har.

Datetime2 eller (date och time)? - 2020-03-10

Nu har jag gått igenom de absolut vanligaste och viktigaste kolumntyperna för tabeller. De två som huvudsakligen saknas är geometry och geography. Dessa används för att spara geografisk och geometrisk data. Jag kommer ha en helt egen bloggserie om dessa två typer senare, eftersom de sällan används i vanliga tabeller och när de används är det oftast i uppsättningar där de används intensivt. Men när jag nu går igenom mina inlägg i serien så inser jag att jag gick igenom kolumntyperna för datum och tider väldigt kort och hastigt i början. Det var mitt allra första inlägg och jag fyllde på med all information i enbart 1 inlägg, trots att datum och tider är ganska komplicerat. Därför kommer jag gå igenom allt en gång till där jag går ner i djupet denna gången.

Vi börjar med att titta på det första exemplet, det är att välja mellan datetime2, date och time. Där det enkla svaret är att man använder datetime2 när man både har tid och datum och de övriga 2 är ganska uppenbara. Och så är enkelt är det för det mesta, använd den minsta möjliga datatypen som finns tillgänglig. Det finns dock fall när det kan vara vettigt att använda en date och en time istället för en datetime2. Låt oss först titta på hur det skulle kunna se ut här under.

Som vi ser här så går det att dela upp en datetime2 i dess beståndsdelar och ha en separat tids- och datumkolumn. Dock riskerar det att vara mindre utrymmeseffektivt om man inte kör med full storlek. Väljer du en mindre storlek så kommer man spara en del bitgrupper (bytes), detta eftersom storleken för date och time är statiska och går därför inte att minska om man har lägre noggrannhet. Som vi tydligt kan se på bilden nedan.

Som vi tydligt ser så kan en datetime2 vara mer effektiv än en date och en time tillsammans, när det kommer till att spara data i databasen. Sedan är det självklart alltid bäst att enbart använda en date eller en time om man inte behöver bägge. Eftersom det är onödigt att spara mer data än man verkligen behöver.

Här kommer dock en väldigt viktig punkt för hela detta inlägget. Det är ibland väldigt effektivt och bra att dela upp en datetime2 i dess två beståndsdelar. Och det kommer i nästa inlägg...

Spara inte en GUID i en sträng - 2020-03-06

Nu när vi går igenom GUID så känner jag att vi behöver gå igenom ett halvvanligt anit-pattern, som jag då och då stöter på där ute. Det är att spara en GUID i någon typ av char. Jag ser till och med ställen där man har det i en nvarchar(36), vilket känns helt och hållet fel. För ni som läser denna bloggen vet ju att en GUID aldrig kan innehålla något som kräver något annat än char(36). Men låt oss titta på vad som blir problemet.

Här ser vi att även den mest effektiva sättet att spara en GUID i en sträng, char(36), är betydligt sämre än att bara spara det i en uniqueidentifier. Och orsaken är enkel, uniqueidentifier är optimerad för en GUID med det är inte en char. Eftersom en char måste kunna spara en massa andra typer av strängar.

Förutom ovanstående så finns det flera problem till. Bland annat att man kan få konverteringsproblem, att man kan råka ha fel saker i kolumnen, att det är otydligt vad man har osv. Så mitt vanliga grundtips fungerar även här, spara rätt sak på rätt plats.

4 månader! - 2020-03-02

Då har bloggen varit igång i 4 månader nu. Tiden går fort när man har mycket att göra, det känns som jag bara är i början av mina bloggambitioner. Det är så mycket mer jag vill få gjort, men allt tar längre tid än man hoppas på. Främst eftersom jag inte vill sluta skriva nya inlägg samtidigt som jag uppdaterar sidan, inläggen är ju trots allt kärnan i bloggen. Ni kommer väl hit för att få tips om SQL Server.

Även denna månaden så blev det 8 stycken vettiga inlägg på bloggen. Det har legat runt det i ett par månader nu så det känns som det nog är där jag kommer ligga under resten av våren. Så räkna med det, jag kommer självklart att uppdatera er hur det går under tiden.

När jag ändå har er på tråden så kan jag avslöja att vi går mot slutet av serien, kolumner i tabeller. Och sen blir det dags för lite mer tips och trix om tabeller. Efter det så kommer ett lite mer designinriktat spår där jag tänkte gå igenom GDPR och SQL. Vilket är kort och gott en massa viktiga saker att tänka på som databasexpert när det kommer till personuppgifter och annan datahantering. Inte så kul kanske, men det kommer vara vettigt.

Ett gratis tips! - 2020-02-26

Idag blir det ett kort tips, men bra tips. Om du gillar att få gratis utbildning om SQL Server, vilket du troligen gör om du hänger här, så har Brent Ozar nu lagt ut en liten del av sitt utbildningsmaterial gratis. Det kommer vara gratis till den 1 April, och jag kommer självklart fräscha upp mina kunskaper inom området. Nedan finns en länk till första delen. (OBS, allt är på engelska.)

https://www.brentozar.com/archive/2020/02/free-fundamentals-of-index-tuning-week-part-1-indexing-for-the-where-clause/

(Om någon undrar så gör jag reklam för detta helt utan få något för det, precis som resten av min blogg. Jag gör det för jag vill att fler ska bli bättre på databaser och SQL Server. Jag ger inga sponsrade rekommendationer.)

Uniqueidentifier (eller GUID) - 2020-02-25

Vi går vidare till nästa kolumntyp, uniqueidentifier. Det är samma sak som en GUID i många andra programmeringsspråk. Den tar upp 16 bitgrupper (bytes) och kan enbart spara en GUID. Nedan kan ni se ett exempel på hur den används.

Huvudsyftet med att spara en GUID i SQL Server är när någon annan del i systemet använder sig av GUID. Det finns sällan någon anledning att använda sig av den för en intern struktur. Ett exempel när man kan använda sig av en GUID är när man vill ha ett id på en tabell för att kunna ha primary key och foreign key relation. Men det skulle jag spontant avråda från, i de flesta fallen är det betydligt bättre att använda en int eller en bigint. Delvis eftersom de tar upp 4 respektive 8 bitgrupper istället för 16, och delvis eftersom det är logiskt med att ha raderna i tabellen numrerade istället för att ha en slumpmässig GUID.

En binary har inte ett entydligt värde - 2020-02-20

Nu är det dags att åter igen titta på en av fallgroparna för en binary, som vanligt gäller detta även för varbinary. En viktigt egenskap för en binary är att den sparar binär data. Det möjliggör att man kan spara lite vad som helst i den. Men det gör också att man måste veta vad man sparar i den, eftersom när du har sparat något i en binary så vet man inte längre vad det är man har där. Låt oss titta på ett exempel här under.

Som vi tydligt ser, så kan 0x41 i en binary både vara siffran 65 och bokstaven A. Med andra ord är det uppenbart viktigt att hålla koll på vad man stoppar in i en binary. Enbart för att du kan dumpa vad som helst i den, innebär det inte att man borde göra det. Vilket ännu en gång sätter fingret på en viktig sak, databasutvecklarna måste ha koll på systemet för att kunna göra ett bra jobb.

Varbinary(max) - 2020-02-17

Vi har ett tag pratat om att ett vanligt användningsområde för binary är att spara filer, men vi har inte pratat om vilken typ av binary som man använder för detta. Det är i princip alltid varbinary(max) som används för att spara filer. Dels eftersom många filer är större än 8K och dels eftersom filerna har en variabel storlek. En varbinary(max) liknar en varchar(max) på många sätt. Men låt oss gå igenom det för säkerhetsskull.

Varbinary(max) kan spara upp till 2^31-1 bitgrupper (bytes), vilket är precis som varchar(max) och motsvarar 2 GB. Den tar upp lika många bitgrupper som längden man sparar plus 2 i overhead. Precis som varchar(max) så går det inte att skapa index för en varbinary(max), och bägge har en rad prestandaproblem som jag pratat om tidigare. Det är orsaken till det jag skrev i förra inlägget, att man gärna undviker en varbinary(max) om det går. Låt oss istället ta en titt på hur det fungerar att använda en varbinary(max).

Som vi ser beter sig en varbinary(max) precis som vi hade kunnat vänta oss. Jag kommer därför lämna just denna typen och i nästa avsnitt gå igenom fler fallgropar kring binary generellt. (Problemen kring prestandan kommer jag återkomma till i en framtida serie om prestandaoptimering.)

Binary är inte min favorit... - 2020-02-14

Nu kommer jag göra en liten utsvävning från mitt vanliga upplägg och inte prata om hur binary fungerar utan hur jag ser på datatypen. (Efter denna utsvävning kommer fler inlägg med kod och på sitt vanliga upplägg.) Detta inlägg innehåller ingen fakta, utan enbart min åsikt. Har du en annan åsikt får du gärna höra av dig till mig så kan vi diskutera om för- och nackdelar.

Jag är generellt skeptisk till att använda binary i en databas för att spara filer. Inte för att det inte går, utan för att de tar upp så mycket plats i onödan. Självklart tar de upp lika mycket plats om man sparar filerna i en mapp, men det är inte en del av databasen. Det jag brukar göra när jag ska spara en fil är att jag sparar filen i en mapp och sedan sparar jag filnamnet i databasen i en vanlig varchar eller något. Sen låter jag programmet, alltså inte SQL Server, hämta upp filen när den behövs.

Vad är då fördelen med att inte spara filen i databasen? Jo, din databas blir mindre och att hämta uppgifter från den går snabbare. Du slipper använda stora binary i dina eventuellt komplicerade queries, vilket kommer underlätta prestandaoptimering längre fram. Du ska också komma ihåg att databaser är dyra medan "vanlig" kod är billig. Har du SQL Server express vill du verkligen inte använda dina 10 GB till en massa stora bilder, och kör du med en betald licens vill du inte fylla din server tunga filer. Om du exempelvis kör din övriga kod i C# så kostar det inget extra att utöka servern för att kunna jobba med fler stora filer. (Ur licenssynpunkt, självklart kostar minne, CPU och liknande alltid pengar.)

En viktig sak att komma ihåg! Om du gör såhär, och inte sparar filen i databasen utan i en mapp, så finns det en stor risk. Det är att din backuphantering blir betydligt mer komplex. För nu måste du se till att hålla koll på bilderna också. Har du dem i databasen så görs det automatiskt av SQL Server, förutsatt att du har en backuphantering. (Jag kommer i framtiden göra en hel serie om backuphantering och då återkommer jag till fler tips och trix, men det är viktigt att komma ihåg att sånt här påverkar backuphanteringen mycket.) Gör du inte ditt jobb rätt kan du efter en databasåterställning ha bilder som saknar ägare och ha ägare utan bilder, och är det systemkritiska bilder så har du ett problem.

När använder man en binary? - 2020-02-12

Nu när vi har börjat förstå oss på hur en binary fungerar är det hög tid att diskutera när det är lämpligt att använda dom. (Som tidigare så gäller allt detta även varbinary.) Och det enkla svaret är när man ska spara en fil, eller motsvarande, i databasen. Ett typiskt exempel skulle kunna vara bilder. Det finns bara ett annat användningsområde för en binary och det är om någon annan del av systemet använder sig av binary och de ska sparas i databasen, eftersom man alltid bör spara data i samma format som de används i övriga delar av systemet. Förutom detta har jag aldrig mött någon verklig användning av en binary. (Har du? Då får du gärna höra av dig till mig!)

Ett tecken på att binary är designade för främst filer är datatypen image. Det är en gammal datatyp som SQL Server kommer ta bort i en framtida version, vilket betyder att du aldrig bör använda image. Binary är den nya versionen som ska användas istället, för att spara liknande data.

Ett typiskt exempel på när binary är praktisk att ha i en databas är för användare. Om man har ett system där man låter användarna skapa ett konto och dessutom ger dom möjlighet att lägga upp en bild. Då kan det vara praktiskt att använda binary i databasen och spara användarnas bilder direkt i databasen.

Binary slänger data som inte får plats! - 2020-02-10

När vi pratar om binary så måste vi först prata om den största risken för dom. Nämligen att en del av talet inte kommer med utan att man får en varning. Det betyder alltså att SQL Server gör en truncate på en del av värdet man försöker spara utan att varna en. Man får helt enkelt ingen overflow-varning. Låt oss titta på ett exempel här under.

På bilden ovan så ser vi att vi försöker stoppa in talet 123456 i 3 olika binary. Som vi också ser så får talet inte plats i de 2 första, eftersom storleken är för liten. Men som vi också märker så får vi ingen varning eller felmeddelande när vi försöker med detta. Och orsaken är enkel, SQL Server sparar helt enkelt bara det som får plats och gör inget mer åt saken.

Läxan från dagens inlägg är mycket enkel. Man måste tänka igenom vad man vill spara i en binary och se till att man har korrekt storlek på den, eftersom man annars kommer spara inkorrekta värden utan att man märker det. (Vill vi spara 123456 så duger det inte med 64 eller 57920.)

Binary och varbinary - 2020-02-07

Då är det dags att gå vidare till en helt ny typ av kolumntyper, binary och varbinary. Här finns det en lång rad saker att tänka på och en del fallgropar, och just därför kommer vi att titta på detta under flera olika inlägg. Där vi tittar på en sak i taget, lite som vanligt här på bloggen.

Binary är en datatyp med fix längd, ungefär som char, där man kan ange en längd mellan 1 och 8000. Binary tar upp 1 bigrupp (bytes) för varje längd.

Varbinary är en datatyp med en variabel längd, ungefär som varchar, som kan ange en längd mellan 1 och 8000. Varbinary tar upp 2 bitgrupper + 1 bitgrupp för varje längd.

Låt oss titta på hur det fungerar att använda en binary. Här under kan ni se hur det ser ut.

Som ni ser så är vår binary ganska oläslig. Men i denna så sparas faktiskt talet helt korrekt. Om vi tittar på nästa bild så kan vi tydligt se det.

Som ni ser så finns värdet korrekt sparat i vår binary, om vi omvandlar det till något som är läsligt. Då kan man fråga sig varför man ska använda sig av en binary överhuvud taget? Framförallt med tanke på alla fallgropar. Och det kommer vi återkomma till i framtida inlägg.

3 månader! - 2020-02-04

Exakt har det gått 3 månader och 2 dagar. Men jag har haft fullt upp så därför blev inlägget lite försenat. Jag är nöjd med månaden som gått, med hela 10 matnyttiga inlägg. Mitt mål med inför nästa månad är 8 inlägg, då jag har ganska mycket annat.

En stor nyhet som jag kan berätta om är att det nu går att registrera sig på hemsidan. Med ett konto har man möjlighet att få mejl varje gång ett blogginlägg kommer ut. (Det går självklart att välja bort detta.) Och under den närmaste tiden så kommer många nya funktioner.

Är det någon funktion du sakar på hemsidan? Eller någon som behöver förbättras? Skicka ett mejl till mig på info@erikdahlen.se så ska jag se om det går att ordna.

Alla siffror blir till true - 2020-01-31

Det finns egentligen bara en kluring när det kommer till en bit i SQL Server, det är att om man försöker stoppa in något annat än 0 så blir det 1. Alltså om man försöker stoppa in 0.45 så får man varken fel eller en avrundning till 0, det blir 1 och därigenom true. Titta på bilden här under.

Som vi tydligt ser så omvandlas alla andra nummer än 0 till en 1:a, och därigenom till true. Att komma ihåg är att det är enbart andra siffror som har detta beteendet, om man försöker stoppa in en slumpmässig sträng så går det inte. Titta exempelvis på bilden här under.

Bit - 2020-01-28

Vi hoppar vidare till nästa datatyp, och nu tar vi den minsta av dem alla, bit. Denna datatyp kan spara 3 olika värden, 0, 1 eller NULL. Här sparar men uppenbarligen enbart en boolean, alltså värden som antingen är true eller false, och inget annat.

En bit tar upp en bitgrupp (bytes), men när du sparar 1 så kan du sen spara 7 stycken gratis. För det är först när du har 9 till 16 som det krävs 2 bitgrupper. Detta mönster fortsätter uppåt. Så, om man har en stor mängd data i sin tabell så kan man räkna med att en bit kommer uppta 1/8 bitgrupp. Med andra ord, det mest effektiva sättet att spara en boolean.

Hur man använder en bit är ganska uppenbart och det som är det viktigaste att tänka på är att 1 anses vara true och 0 false. Här under kan du se hur man skapar en bit i en tabell.

Använd float när du har ett flyttal - 2020-01-23

Från förra inlägget så har vi kvar frågan, när ska man använda sig av en float förutom vid väldigt stora eller små tal. Jo, när onoggrannheten är något man önskar sig. Och då kommer självklart följdfrågan, när önskar man sig onoggrannhet? Och det är precis det vi ska gå igenom idag.

Det första, och det som ni troligen kommer använda er av mest, är när siffrorna man får in i databasen är flyttal av samma typ som en float. Ta till exempel double i C#, den är definierad precis som en float i SQL Server. Så, om det är ett C# program som genererar/hämtar talet som ska sparas i din databas och talet är en double bör du spara det i en float. (Det finns liknande matchningar för i princip alla datatyper, exempelvis är en real i SQL Server en single i C#.)

Orsaken till detta är att det kan bli liknande misstag som vi tidigare har tittat på om man blandar ihop datatyperna. Exempelvis kan det bli ett problem om man vill spara en double i en decimal eftersom den kanske inte får plats. Men även om den får plats så finns det en risk att en double är avrundad eftersom den är oprecis medan när den senare är sparad i en decimal så kanske man antar att den är precis och därigenom missar att talet är en avrundning.

Slutsatsen är alltså enkel, använd float om det du får in i databasen är ett flyttal. Vilket kräver att du som designar en databas har koll på vad det är du sparar i den. (Om det inte var uppenbart från början så säger jag det nu, man ska aldrig bygga en databas innan man vet vad man ska ha i den och vad den ska användas till.)

Det finns ett extra tillfälle när onoggrannhet är något man önskar sig. (Men det är enbart i ovanliga fall.) Det är när man ska skapa vissa typer av simuleringar, och det är till ens fördel att en del tal inte är exakta. Eftersom då skapas lite brus i datan gratis. Vi såg ett exempel på detta när vi multiplicerade 0.1 ett stort antal gånger. Om målet är att skapa en simulering av ett verkligt problem kan brus i datan vara till ens fördel, eftersom det efterliknar verkligheten bättre. Och fördelen med denna typ av brus är att du alltid kommer få samma brus om du genomför samma simulering igen, till skillnad från om du inför brus manuellt genom någon typ av slumpgenerator. (Men som sagt, detta använder man sig mycket sällan av.)

När vill vi använda en float? - 2020-01-20

Nu när vi har tittat på float i ett antal inlägg för att kolla på dess problem så kan man få uppfattningen att float alltid är sämre än decimal. Och så är det ju självklart inte. Det finns 3 huvudsakliga fall när man gärna vill använda en float. Det är vid väldigt små tal, det är vid väldigt stora tal och det är när man gärna vill ha en onoggrannhet. Låt oss först titta på väldigt stora tal, på bilden under.

Här ser vi tydligt att detta stora tal går bra att spara i en float och i en decimal. Om vi i följande 2 bilder testar att multiplicera med 10 så ska vi se att decimal inte klarar av så stora tal längre, men det gör float.

Slutsatsen är mycket enkel, ibland har man så stora tal att man behöver använda en float. Exakt samma sak gäller för mycket små tal, men jag kommer inte visa det för det känns lite för uppenbart. (Testa gärna själv om du känner dig osäker.) Det betydligt mer intressanta fallet ska vi titta på i nästa avsnitt, när onoggrannhet är något vi önskar oss.

När är float exakt och oexakt? - 2020-01-15

Orsaken till att float inte kan spara talet 0.1 exakt är ganska enkelt, float sparar decimaltal i bråk som 1/2^n. Alltså 1/2, 1/4, 1/8, 1/16 osv. Och utifrån detta går det inte att spara talet 0.1 exakt, men talet 0.5 går bra eftersom det är 1/2. Låt oss titta på ett tal som går bra att spara.

Som ni tydligt ser så blir detta tal exakt, och orsaken är att 0.15625 också är 1/8+1/32. Alltså går det att spara tal som är en kombination av ett antal 1/2^n exakt. Alla andra tal kommer vara ungefärliga, exempelvis det nedan.

Här kan man tydligt se att 0.15624 inte går att spara exakt i en float. Det är det viktiga i detta inlägg, alla tal som går att skriva som en kombination utav flera 1/2^n är exakta, alla andra kommer vara en avrundning.

Jag skulle säga att orsaken till detta är ganska matematisk, och det beror på att float sparar sina tal i basen 2 istället för basen 10 som vi normalt gör. Och alla olika baser har egentligen samma problem, fast för olika tal. I basen 10 går det bra att spara talet 1/10 men inte 1/3. I basen 2 går det bra att spara 1/16 men inte 1/10. (Vill du djupdyka i detta måste du läsa på en del om matematik, och denna blogg kommer lämna just den matematiska delen nu och fortsätta titta på databaser och SQL Server.)

Float kan inte spara 0.1 exakt - 2020-01-13

Orsaken till problemet i förra inlägget, att en summa av många 0.1 aldrig blir 8.0, är att det finns inget exakt tal 0.1 för float. (I hela detta inlägg så gäller samma sak för real.) Utan talet 0.1 är hela tiden en avrundning och när man adderar många avrundningar på varandra så kan det ibland bli fel.

Tittar vi på en decimal så kan vi se att talet 0.1 går att ha exakt, enligt bilden nedan. Om man måste ha exakta tal så går det inte att använda float.

Om vi istället tittar på en float så kan vi tydligt se att den inte är exakt 0.1 när vi jämför den med en decimal, enligt bilden nedan. Och det är denna noggrannheten som orsaker problemet.

När man tittar på detta så blir det ganska uppenbart att det kan bli ett problem med float om man behöver exakt noggrannhet. Vilket float aldrig kan garantera. Det är dock viktigt att komma ihåg att avrundningsfelet ligger bortom den 15 siffran och därigenom uppfylls kravet på att ha 15 siffrors precision som jag nämnde i början av serien om float. Enda orsaken till att det blir ett problem i detta exempel är att vi använder 0.1 i en while-loop vilket tillåter osäkerheten att växa. (I nästa inlägg fortsätter vi titta på detta för att förstå varför det blir såhär.)

Problem med float! - 2020-01-10

Det finns en rad problem och fallgropar med float och real. Och dessa kan enkelt sammanfattas som problem med precisionen. Låt oss ta en titt på ett exempel för att förstå vilken typ av problem som kan uppstå.

Om vi tittar på bilden här under så kan vi tydligt se att en float som har värdet 8 inte riktigt har värdet 8, eftersom då borde while-loopen ha stannat vid 8.

När vi tittar på denna bilden så ser det lite konstigt ut, variabeln har ju värdet 8 så den borde ju ha stannat där. Men om vi minskar precisionen på variabeln så kommer vi tydligare se vad det är som händer.

Här ser vi tydligt att det som händer är att 8.0 inte riktigt finns, utan 7.999 och 8.099 finns. Och eftersom jämförelsen i while-loopen är exakt så kommer den aldrig att bryta. Och orsaken till varför talet 8.0 inte finns, trots att rent matematiskt så borde det finnas beror på hur en float fungerar. Och det känns som vi behöver ett helt inlägg för att djupdyka i detta, så det kommer. Men läxan från dagens inlägg är att float är oprecisa tal, och ska aldrig användas om man behöver ha exakta tal. (Du får samma beteende för real som för float(24).)

Float eller real? - 2020-01-08

När man använder sig av float och real är det viktigt att komma ihåg deras precision. Nämligen att real enbart kan hålla 7 siffrors noggrannhet medan float kan hålla 15 siffror. Det är faktiskt den största anledningen till varför jag ofta behöver använda float istället för real. (Den andra anledningen skulle ju vara för att spara betydligt större tal, men det är sällan man behöver större tal än vad real erbjuder.)

Om vi testar att stoppa in ett tal med 8 siffror i både float och real, kan vi enkelt se att real måste avrunda.

Som vi ser fungerar allt som vi hade förväntat oss. (Hade vi flyttat decimaltecknet åt något håll hade vi fått samma beteende, prova själv om du vill testa.) En sak som går att göra med float men inte med real är att bestämma storleken. Om vi anger en float(24) kommer vi i praktiken att få en real. Som du kan se här under.

Du kan med andra ord välja att enbart använda dig av float och aldrig real. Vilket man gör spelar ingen roll, och det finns olika åsikter om det. Det viktigaste är att vara konsekvent i hela databasen, så använd inte float(24) ibland och real ibland.

Hur ser lönen ut för en SQL Server expert? - 2020-01-07

Nu är löneundersökningen gjort, som jag för mindre än 1 månad uppmanade er att delta i, och resultatet finns att tillgå på länken här under. Gå in och titta själva för att se all matnyttig info som finns där.

https://www.brentozar.com/archive/2020/01/the-2020-data-professional-salary-survey-results-are-in/

Det finns några slutsatser man kan dra från denna studie. (OBS! det är inte supermånga från Sverige som deltog, så man kan inte anta allt för mycket från den.) Det första är att folk rent ut sagt är dåliga på att ange siffror rätt (troligen). Det är 1 person i Sverige som anger att hen tjänar 6280 i månaden, och 1 person som tjänar 426000 i månaden. Jag misstänker att dessa är fel så jag har tagit bort dem från min analys.

När jag tittar på siffrorna så ser jag att medianlönen för er SQL Server experter är ungefär 50 tusen i månaden. Vilket jag skulle säga är en bra lön, jämfört med många andra yrken. Jag kan också se att 3 personer tjänar mellan 30 och 40 tusen, och dessa personer har jobbat minst antal år med SQL Server. Jag ser att flest personer ligger mellan 40 och 50 tusen, nämligen 10 stycken. Sen ligger 5 personer mellan 50 och 60 tusen, och 6 personer mellan 60 och 70 tusen. Och slutligen har vi 3 personer som ligger mellan 70 och 80 tusen.

Där har vi det, en sammanställning över vad en SQL Server expert borde tjäna i Sverige idag. Jag hoppas alla er som ligger i den lägre delen av kurvan tar med sig detta till årets lönesamtal. Ingen av oss vill ju bidra till lönedumpning ;-)

Float och real - 2020-01-03

Det finns 2 kolumntyper i SQL Server som tillåter att man sparar icke exakta tal. Det är float och real, där float är den större av de två.

Real tar upp 4 bitgrupper (bytes) och kan spara upp till 7 siffrors precision. En real kan spara tal från -3.40E+38 till -1.18E-38 samt 0 samt 1.18E-38 till 3.40E38. Detta betyder att real kan spara både mycket stora och mycket små tal, både på den negativa och positiva sidan.

Float tar upp 8 bitgrupper och kan spara tal med upp till 15 siffrors precision. Det är möjligt att spara tal från -1.79E+308 till -2.23E-308 samt 0 samt 2.23E-308 till 1.79E+308. Så med andra ord ungefär som real men med betydligt högre upplösning och betydligt större tal.

Hur stora tal man kan spara är inget som jag lägger på minnet, men däremot är det viktigt att förstå hur dessa kolumntyper fungerar och när man ska använda dem. Och det kommer jag gå igenom under en rad olika inlägg framöver. På bilden nedan så kan ni se hur man använder dem.

2 månader! - 2020-01-02

Nu har ännu en månad med bloggen gått, och jag tackar alla er som har följt den. Det är ju trots allt för er jag skriver den. Under den senaste månaden har det blivit 7 matnyttiga inlägg, vilket är lite färre än de 10 jag hade hoppats på. Orsaken är väldigt enkel, julen åt upp min tid mer än jag hade tänkt mig, vilket nu när jag säger det känns ganska uppenbart.

Ni som har följt mig under hela månaden har märkt att det har tillkommit en rad nya funktioner på sidan, bland annat att man enkelt kan kopiera koden. Jag förväntar mig att sidan kommer fortsätta att uppdateras under den kommande månaden. Parallellt med att jag hoppas kunna skriva 10 nya inlägg under månaden.

Om ni har något som ni önskar att jag tar upp lite mer i detalj är det bara att skicka ett mejl till mig, på info@erikdahlen.se. Det kan även vara önskemål eller förslag om förändringar på själva sidan. Nu när bloggen är under uppbyggnad så har man större möjlighet att påverka ;-)

Om man tvingar decimal att avrunda. - 2019-12-19

Vi har tidigare undersökt varför decimal kan ha högre noggrannhet än money, trots att de har lika många decimaler. Och svaret var att decimal håller koll på extra decimaler i bakgrunden. Men låt oss då testa vad som händer om vi tvingar decimal att enbart ha 4 decimaler hela tiden.

En viktig sak att förstå här är att en dator alltid måste göra en avrundning mellan varje steg i en komplicerad uträkning. Varje gång en uträkning sker som har många/oändligt många decimaler måste en dator slänga några vid varje steg i en uträkning. Och vi ska nu titta på hur det blir för decimal när vi tvingar den att avrunda till 4 decimaler i varje steg.

Som vi tydligt ser så får inte en decimal högre noggrannhet än en money när vi tvingar den att också avrunda till 4 decimaler i alla leden. Så nu anser jag att vi har tydligt demonstrerat vad det är som händer, om du fortfarande känner dig osäker så ladda ner koden och testa dig fram eller läs igenom dokumentationen för SQL Server.

En annan observation vi gör här är att decimal nu har valt att avrunda talet enligt vanliga matteregler och inte kört en floor och bara slängt den femte siffran. Frågan den nyfikne då ställer sig är vad som händer om vi istället gör detta för money.

Nu ser vi att money beter sig på samma sätt som tidigare, nämligen att money kör på floor hela tiden. Personligen skulle jag säga att det är en styrka, till skillnad från decimal som ibland kör med floor (titta i ett tidigare inlägg) och ibland med vanlig avrundning. Jag skulle säga att rent generellt så har money betet sig väldigt konsekvent under alla inlägg i denna jämförelsen medan decimal har bytt skepnad. Det viktiga att ta med hem från dessa inlägg är att det finns en rad fallgropar kring olika tal. (Normalt måste man undersöka systemets/projektets krav vid varje ny databas man ska bygga. Och tur är väl det, hade det varit enkelt att köra med en "one size fits all" hade en dator kunnat göra detta och vi varit arbetslösa.)

Jag kommer nu avsluta jämförelsen mellan just decimal och money, det är dags att gå vidare med bloggserien. Nästa gång kommer vi titta vidare på olika kolumnval för tabeller.

Varför kan decimal ha högre noggrannhet i uträkningar? - 2019-12-16

Hur kommer det sig att decimal kan ha högre noggrannhet än money? Jo, egentligen är det ganska enkelt, det finns extra data i bakgrunden. Låt oss titta igenom ett exempel för att förstå vad detta betyder.

Om vi tittar på bilden under, så ser vi att det finns en begränsning i hur många decimaler som denna decimal kan hålla.

Som vi tydligt kan se så klarar inte denna typen av decimal att hålla samtliga decimaler, eftersom de 6 sista siffrorna alla är 0. Tittar vi istället på bilden här under så ser vi att det ändras.

Precis som tidigare så ser vi att med en decimal med mindre storlek så kan vi ha högre noggrannhet i detta exemplet. Frågan man kan ställa sig är varför. Och svaret är att en decimal med mindre storlek kan ha mer extra data i bakgrunden. Låt oss titta på nästa bild för att se ett exempel på detta.

Som vi tydligt kan se här så finns det mer än 4 decimaler i svaret, så fort vi inte längre tvingar SQL Server att max visa 4 decimaler som vi gjort tidigare. Det är alltså så att i bakgrunden har det funnits fler decimaler än vad vi har angivit i våra decimal. Och orsaken till att vi inte har fått samma resultat för money, är att SQL Server inte kan tilldela dem fler extra decimaler i bakgrunden.

Vi har i detta inlägg sett att SQL Server ibland kan tilldela tal extra decimaler i bakgrunden när den genomför komplicerade uträkningar. För att öka noggrannheten på svaret. Dock måste vi veta om när det sker och inte. Det är tyvärr så att man i varje enskilt fall måste undersöka vad som krävs för just detta fallet, och vilken datatyp samt noggrannhet som behövs. Det finns ingen "one size fits all". I nästa inlägg så ska vi fortsätta att undersöka detta för att på riktigt förstå vad som händer.

Fallgropar finns både för money och decimal - 2019-12-13

Nu när resan fortsätter ner i djupet, om skillnaden mellan decimal och money, låt oss först titta på var vi stod. I denna första bild här under så ser vi att med en decimal får vi högre noggrannhet för färre bitgrupper (bytes).

Om allt var enkelt borde det vara avgjort nu, decimal är bättre på alla vis än money. Men tyvärr så är det inte riktig så enkelt. Låt oss ändra lite i storleken på decimal och se vad som händer.

Från denna bilden så kan vi dra 2 stycken lärdomar. Först och främst att storleken för en decimal spelar roll, och ökar vi storleken här så minskar vi helt plötsligt upplösningar på svaret. (Orsaken till detta ska vi titta lite på i nästa inlägg.) Och för det andra så ser vi även decimal avrundar på samma sätt som money, nämligen att de gör en floor. Vilket betyder att man inte avrundar utan man slänger alla överblivna siffror. Det är standard inom så gott som alla programmeringssystem. (Vi får prata om avrundning i SQL Server i framtiden.)

På nästa bild så ser vi att storleken på decimal ökar om vi skulle öka upp antalet nollor, vilket inte händer för money. Helt plötsligt så skulle man spara en del plats på att använda sig av en money istället.

Som ni ser så spelar det stor roll om man använder sig utav money eller deciamal. En viktig observation här är att money beter sig konstant lika dant oavsett vad som händer men det gör inte decimal. Och det ska vi prata lite mer om i nästa inlägg.

Vad tjänar du? En väldigt viktig fråga! - 2019-12-12

Denna gång kommer något helt annat. Själv följer jag andras bloggar för att hålla koll på vad som händer i fältet. Och här kommer ett inlägg från en blogg jag själv följer. Inlägget går ut på att folk som jobbar med databaser och SQL Server ska gå in och ange vad de jobbar med och vad de tjänar, så vi alla kan bli en aning bättre på veta vad vi borde ligga någon stans. Och eftersom det huvudsakligen spelar för roll vad andra tjänar i Sverige så ber jag er alla gå in och ange vad ni tjänar.

https://www.brentozar.com/archive/2019/12/are-you-underpaid-lets-find-out-the-data-professional-salary-survey-is-open/

Fördelen är enkel, om många berättar vad de tjänar som databasprogrammerare/databasadministratörer/databasexperter osv. så kan vi veta om vi bör kräva högre lön eller inte. Och för er som redan har bra lön är det ju bra om det inte finns andra som dumpar lönen för vårt yrke. Så gå in och uppge vad du tjänar. (Allt sker så klart anonymt.)

Var försiktig när du räknar med money - 2019-12-10

OBS! Exemplet i denna post är hämtad från följande inlägg på stackoverflow. Vill du hellre läsa originalet istället för min version gör gärna det på följande länk här under. För er som vill läsa min svenska version av problemet kan göra det här.

https://stackoverflow.com/questions/582797/should-you-choose-the-money-or-decimalx-y-datatypes-in-sql-server

Det är så att det ibland inte alls är bäst att spara belopp i money. Och det kan det vara när man ska använda beloppen i olika uträkningar i en mer komplicerade query. Här under ser vi ett exempel på exakt samma uträkning som får två olika svar beroende på om man använder money eller decimal.

Som ni ser så tappar money bort decimalerna i uträkningen medan decimal inte gör det. Detta gör att man måste vara på sin vakt när man använder money. Men som ni ser från bilden här under så går det att använda money i detta exemplet så länge man inte använder money i variabeln för divisionen.

I nästa inlägg kommer vi gå lite djupare ner på varför det blir såhär. Men det viktiga att ta med sig hem ifrån detta inlägg är att det gå bra att spara belopp i money om man inte använder det i komplicerade uträkningar. Ska man göra det måste man tänka igenom saken lite noggrannare. (Viktigt att komma ihåg är att decimal också innehåller liknande fallgropar, som jag snart kommer gå igenom.)

Money och smallmoney - 2019-12-05

Då går vi vidare till nästa 2 typer av nummer, även dessa med fix noggrannhet. money och smallmoney. Som det låter så är dessa till för att spara belopp i. Bägge har alltid 4 decimaler, så länge man inte kör med Informatica vilket jag aldrig har sätt någon göra men i så fall använder de enbart 2 decimaler.

Smallmoney är en mindre datatyp som enbart tar upp 4 bitgrupper (bytes). Den tillåter enbart att man sparar nummer från -214,748.3648 till och med 214,748.3647. Orsaken till att dessa sällan används är att 214 tusen är inte så himla mycket, så det är ofta man behöver möjlighet att kunna spara större tal. Kom ihåg att om din databas ska spara andra valutor så kan 214 000 ibland vara ganska små summor. (Exempelvis är den japanska yenen inte värd så mycket.)

Money är nog den vanligaste typen och den tar upp 8 stycken bitgrupper (bytes). Den tillåter att man sparar tal från -922,337,203,685,477.5808 till och med 922,337,203,685,477.5807. Här under kan du se hur man använder dem.

När det kommer till belopp är det ofta att rekommendera att spara dem i money, dels eftersom det är en exakt siffra och dels att användaren av databasen direkt kan se att det är belopp som är sparade i dem. Jag brukar alltid rekommendera att man använder rätt kolumntyp, då blir det enklare när många ska använda datan/databasen. (Kom ihåg att även om du i nuläget tror att du kommer bli den enda som jobbar med den, så ändras sånt ofta med tiden.)

Även parametern är avgörande för decimal - 2019-12-03

Under förra inlägget i serien så såg vi att det spelade roll för en decimal vilken storlek man valde. Och jag visade att två olika tabeller där enbart storleken skiljde sig åt kunde spela stor roll för vilken execution plan som SQL Server väljer. Nu tänkte jag lite fort visa vad det beror på. (Utan att titta ner i de riktigt djupa detaljerna.)

Vilken execution plan som SQL Server väljer beror i detta fallet helt på vilken parameter man använder i sin where clause. Om vi tittar på bilden under så kan vi se att bägge execution plan går att få för tabellen med mindre storlek.

Som ni ser så är det valet av parameter som styr vilken execution plan som SQL Server väljer. Men från bilden under så ser ni att gränsen skiljer sig åt om man väljer den större storleken.

Som ni ser så spelar det roll vilken parameter man väljer. Och att gränsen där det spelar roll skiljer sig beroende på storleken för kolumnen. Med andra ord, alla val ni gör när ni designar en tabell spelar roll för prestandan längre fram. Det är det viktigaste jag vill lära er i detta inlägg, om ni gör dåliga val av tabeller så kan det påverka prestandan. (Detaljer om execution plan kommer i framtida inlägg.)

1 månad! - 2019-12-02

Då är det dags att fira att bloggen är 1 månad gammal! Inget superstort, men det gäller att fira de små framstegen. Under månaden som gått har vi huvudsakligen tittat på kolumner i tabeller. Och det kommer vi fortsätta med, tills vi går vidare med mer avancerade saker kring tabeller.

Jag tänkte passa på att nämna några saker som har hänt denna månaden. Jag har skrivit 12 stycken matnyttiga inlägg, och hoppas att det blir åtminstone 10 stycken nu under december. Och sen kan vi titta på bilden nedan för att se hur många besökare bloggen har haft, och jag hoppas att det ska öka.

Jag kan också berätta att jag planerar att snart uppdatera utseendet på sidan. Då ska ni kunna ladda ner den kod jag använder mig av, för att slippa skriva av den. Och en rad nya saker kommer också bli möjligt, så stanna kvar på denna blogg så kommer ni snart märka förbättringarna.

För decimal spelar storleken roll - 2019-11-29

Låt mig här under visa ett kort exempel på att det spelar roll vad man gör för val med storleken. Om man ökar storleken kommer det att få effekter på prestandan, trots att det sker inom begränsningen så att lika många bitgrupper (bytes) sparas. Här under ser ni en bild som visar att dessa två olika storlekar på decimal tar upp lika mycket plats.

Som ni ser så är dessa två tabeller nästan identiska, med helt identisk data. Och den enda skillnaden mellan de två är storleken på decimal, och i databasen tar dessa två storlekar upp exakt lika mycket plats. Då hade man kunnat tänka sig att det inte spelar någon roll vilket man ska välja, men titta då på nästa bild.

Som ni ser så blir det ganska olika execution plan för dem. Ni kan säkert själva lista ut att det kan spela roll för prestandan vilken SQL Server använder sig av. Så här kan jag ge ett tips, tänk noga igenom alla val som ni gör! (Vi kommer inte i detta inlägg gå igenom hur man tolkar en execution plan och hur man kan använda den för att optimera databasen. Det kommer i framtida serier. Men nu vet ni i alla fall om att tabellval spelar roll för prestandan.)

Decimal och numeric - 2019-11-26

Ofta när man ska spara tal så räcker det inte med heltal utan man behöver kunna spara decimaltal. Och just därför finns flera typer av decimaltal. Vi börjar med att gå igenom de 2 med fix längd (noggrannhet), decimal och numeric.

Dessa två typerna, decimal och numeric, är i bokstavligen samma typ. Så det går i praktiken att använda sig utav vilken man helst vill. Personligen använder jag oftast decimal eftersom jag tycker det låter naturligt att spara decimaltal i en decimal. Det jag kan starkt rekommendera är att använda samma överallt, oavsett vilken man bestämmer sig för.

När man använder en decimal så behöver man ange vilken storlek och var man vill ha decimaltecknet. Det bestäms såhär, decimal(n,m) där n är längden och m är positionen på decimaltecknet. Exempelvis decimal(5,2), som tillåter tal mellan -1000 och 1000 och med två decimalers noggrannhet. (Från och med -999,99 till och med 999,99)

När man ska använda sig utav en decimal är det viktig att först fundera noga på vilken storlek man behöver. Större tal kräver större utrymme och större prestanda. Dock är det inte linjärt utan det finns vissa steg. Decimal med längden 1-9 tar upp 5 bitgrupper (bytes), längden 10-19 tar upp 9, 20-28 tar upp 13 samt 29-38 tar upp 17. Större än 38 går inte att lagra i en decimal. (Ett exempel kan ni se i bilden nedan.)

Trots att det tar upp lika mycket plats i databasen att ha en decimal(5,2) som det tar att ha en decimal(9,4) rekommenderar jag inte att alltid använda den större. Visst är det bra att kunna lagra större tal utan att det krävs extra utrymme, men det alltid mer komplicerat än så. Jag rekommenderar alltid att försöka skapa begränsningar i systemet, som stämmer överens med ens affärslogik.

Tinyint eller char i tabeller? - 2019-11-22

När man funderar på att använda sig utav en tinyint för att spara grupptillhörighet så är det viktigt att komma ihåg att även char finns. Bägge dessa två tar upp en bitgrupp (byte) och är således lika effektiva. Men det finns en viktig skillnad, tinyint är heltal medan char är bokstäver. Alltså bör du spara grupper som är numrerade i tinyint och grupper som är bokstavsspecifika i char.

Ett tydligt exempel på detta är kön. Det går alldeles utmärkt att spara kön i en tinyint, och exempelvis använda 1 som man, 2 som kvinna, 3 som trans och 4 som okänd. Men jag skulle rekommendera att använda en char istället, och exempelvis använda m som man, k som kvinna, t som trans och o som okänd. Det spelar ingen större roll för prestandan, men det är enklare att läsa och risken är mindre att man blandar ihop vilken som är man, kvinna, trans och okänd.

En viktig rekommendation från ovan exempel, använd helst inte svenska ord inom kodning. Använd helst engelska, exempelvis male, female och unknown. (Det är oftast bäst att hålla hela databasen samt programmen som använder den helt på engelska, för att minimera risken för missförstånd.)

Heltal i tabeller - 2019-11-20

Efter en lång genomgång av texter i tabeller så är det dags för olika typer av heltal. Dessa är betydligt enklare än andra kolumntyper, det finns inte så många olika funderingar. Det enda som avgör om du bör använda dig utav en tinyint, smallint, int eller bigint är hur stora heltal du måste spara. Desto större du väljer, desto mer plats tar de upp.

Tinyint tar upp 1 bitgrupp (byte) och tillåter tal från 0 till och med 255. En vanlig användningen för denna typen av heltal är när man ska spara enum, eller olika grupper.

Smallint tar upp 2 bitgrupper och kan spara tall från -32,768 till och med 32,767. Detta är troligen den ovanligaste heltalstypen, och används sällan i verkliga miljöer.

Int tar upp 4 bitgrupper och kan vara ett heltal från -2,147,483,648 till och med 2,147,483,647. Denna används för de flesta tal när man behöver använda sig utav ett heltal.

Bigint tar upp 8 bitgrupper och kan vara ett tal från -9,223,372,036,854,775,808 till och med 9,223,372,036,854,775,807. Denna heltalstyp behövs när man ska spara stora tal.

Här under kan ni tydligt se att de större heltalstyperna tar större plats för att spara samma siffra. Vilket tydligt visar valet som finns, ge möjlighet för stora tal eller spara utrymme.

Varför inte alltid använda sig av varchar(max)? - 2019-11-18

Efter förra inlägget skulle man definitivt kunna ställa sig frågan varför man inte bara omvandlar alla text och ntext till varchar(max) och nvarchar(max). Och det är en bra fråga, och svaret är lite komplicerat. Om man ska spara väldigt långa texter så kan man absolut behöva använda sig utav (max). Och i så fall gör man det. En varchar(max) fungerar att använda istället för en varchar(n). Där n kan vara ett tal mellan 1 och 8000. Det kan man se på bilden här under.

Som ni ser så fungerar båda lika bra för att spara en text. Så man skulle helt enkelt kunna spara alla texter i varchar(max), och då kan man ställa sig frågan varför SQL Server ens har varchar(n). Och svaret är självklart att det finns fördelar med varchar(n).

Tyvärr kommer jag inte beskriva alla fördelar med varchar(n) istället för varchar(max) just nu. Det är ganska komplicerat och kommer finnas med i framtida inlägg när vi diskuterar optimering och index. Det du bör komma ihåg är att varchar(max) kan komma att kosta prestanda när du bygger komplicerade queries. Exempelvis som du ser i bilden här under så kan man inte använda varchar(max) som primary key. (Fler begränsningar finns.) Så använd varchar(max) enbart där du måste. (Vi kommer även prata om hur man kan gå runt en del av begränsningarna i framtida inlägg.)

Använd aldrig text och ntext - 2019-11-14

När det kommer till att spara text i kolumner så kan man tro att det är lämligt att ibland använda sig utav typerna text och ntext. Men det är helt fel, trots att de fortfarande går att använda. Tittar vi på bilden här under så ser vi att det går helt utmärkt.

Orsaken till att man inte ska använda dem är att SQL Server kommer blocka bort dem. Det innebär inte att du omgående måste bygga om din databas, men det innebär att någon gång i framtiden så kommer du inte längre kunna uppdatera din SQL Server om du använder dem. Det du bör göra är att aldrig använda dem när du skapar nya tabeller och suggestivt ta bort dem varje gång du stöter på dem.

Om du har en databas med någon utav dessa datatyper så är det dags för dig att göra upp en plan för att byta ut dem. Det första du måste tänka på är vilken kolumntyp du ska ha istället. Och det första är enkelt, ntext motsvarar nvarchar och text motsvarar varchar. En lite klurigare sak att fundera kring är att bestämma en längd, eftersom text inte behöver en angiven längd så måste du avgöra vilken längd du vill ha. Ett sätt är att undersöka längden som redan finns i tabellen, ungefär som bilden nedan.

När man väl har bestämt längden och datatypen kommer den svåra delen. Det gäller att gå igenom så att man ändrar på alla ställen där det behövs, finns det procedurer, vyer eller annat som förväntar sig att kolumnen är en text så måste man modifiera även dem.

Collate på en enskild kolumn - 2019-11-13

Det är inte så att man enbart kan sätta collate för databasen, trots att det är det vanligaste. Man kan faktiskt sätta collate på varje kolumn. Allt för att kunna spara flera olika typer av texter i samma tabell i samma databas. Det fungerar som bilden nedan visar.

Som ni tydligt ser så går det bra att spara olika typer av char i samma tabell. Vi kommer i framtida inlägg prata mer om collate, men det viktiga här är att komma ihåg att man kan vilja/behöva modifiera collate i vissa specialfall.

Dock måste jag erkänna att jag nästan aldrig använder mig utav detta och jag ser sällan någon annan heller göra det. Men det är lika bra att vi går igenom det också, eftersom det finns och ni måste kunna förstå att möjligheten finns samt känna igen det när ni ser det. (Orsaken till att det inte används så mycket är att man helt enkelt kan använda sig av nchar om man vill kunna använda andra tecken.)

Collate påverkar char - 2019-11-11

Jag funderade ett tag efter mitt förra inlägg och insåg att de utav er som inte ännu är experter på SQL Server kanske tycker att det är lite konstigt att svenska tecken som ö finns med men inte från andra språk. Orsaken är att man kan ställa in språket på en databas, och det påverkar vilka tecken som finns med i en char och varchar.

För att bestämma vilket språk en databas ska köra på så måste man ställa in collate. Det gör man enkelt via ett anrop enligt bilden nedan. Kom ihåg att när man gör det såhär så ställer man in det för hela denna databasen.

När man har ändrat collate för sin databas så påverkar den hur char och varchar fungerar i den databasen. Om ni tittar nu så kommer char kunna innehålla en ж medan ett ö omvandlas till ett o. Alltså inte en så bra inställning när man programmerar i Sverige.

Som ni ser så spelar collate stor roll för en databas. I fortsättningen kommer jag att använda mig utav en svensk version så att jag kan ha å, ä och ö i mina char. Det finns fler viktiga saker att tänka på när man väljer collate, men det kommer vara del utav en framtida serie om "viktiga databasinställningar". Jag ville bara förklara att det inte är magi som avgör vilka tecken som man kan använda i en char, utan det är en inställning. Men kom ihåg lärdomen från detta, om du är osäker på vilka tecken du kommer lagra så är alltid nchar och nvarchar att föredra.

Bonusinlägg om char - 2019-11-08

Idag blir det ett bonusinlägg, eftersom jag har stött på ett problem som jag inte kände till tidigare. Och eftersom du läser dessa så kanske du inte heller känner till det.

Jag har tidigare nämnt att char inte kan hantera alla tecken, till skillnad från nchar. Men när vi tittade på något exempel tidigare så visade det sig att när man försöker stoppa in ett okänt tecken så blir det ett frågetecken. Tyvärr blir det inte alltid så. Titta på bilden här under.

Som vi ser så kan SQL Server omvandla tecknen. Som här ovan där ņ omvandlas till n. Med andra ord så kan något som sparas i en char egentligen ha varit något annat. Jag är ingen språkexpert så jag vet inte skillnaden på dessa, men jag vet att skillnaden är stor på ett o och ett ö i svenskan så jag får antar att andra länder kan se stor skillnad på ņ och n. Slutsatsen är alltså, kom ihåg att använda er av nchar och nvarchar när det behövs. (Trots att de kostar dubbelt så många bitar.)

Fler beslut om texter i tabeller - 2019-11-07

Efter förra inlägget i denna serie så kan man bestämma sig om man vill ha nvarchar eller varchar. Men när valet är gjort så måste man bestämma sig om man vill ha nvarchar eller nchar, respektive varchar eller char. Skillnaden mellan dem är att de som har var med i namnet har en variabel längd medan de andra har en fix längd.

Låt oss först gå igenom vad det betyder med variabel längd eller inte. Jo, det menas med hur mycket plats det kommer ta upp i databasen. Det går alltså utmärkt att ha en sträng som är kortare än maxlängden i både varchar och char. Längden man anger efter både en varchar och char är maxlängden och det går inte att ha längre strängar än vad som är angivet. Alltså skillnaden är att i en sträng som sparas i char(10) alltid kommer uppta 10 platser i databasen, oavsett storleken på strängen. Medan i en varchar(10) så kommer platsen i databasen variera beroende på strängens längd. Kolla in bilden här under.

Som ni tydligt kan se så tar char(3) alltid upp 3 platser, medan varchar tar upp olika mycket beroende på hur lång strängen fakstikt är. Från detta kan man dra slutsatsen att varchar är bättre än char. Och för nästan alla texter som ska sparas så stämmer detta mycket väl. Så det korta svaret är, är du osäker använd en typ med var, framförallt med användarinförd data.

När ska man använda char då? Varför finns denna kolumntyp ens? Jo, för det är inte så enkelt. När man har en kolumntyp som använder sig av var så kommer det krävas 2 extra bitgrupper (bytes) för varje rad för att hålla koll på den faktiska längden. Om man vet att längden alltid kommer vara den samma för denna kolumn så sparar man lite extra plats genom att använda char. Ett typiskt fall att använda sig utav char är när man har en tabell med ordernummer och dessa innehåller både siffror och bokstäver men alltid har samma längd.

När jag själv använder mig av texter i databaser så skulle jag säga att den vanligaste är nvarchar för alla texter som jag inte helt säkert vet vad som kommer finnas i dem och ibland använder jag char för de fall när man vet vad som ska finnas i dem och då är längden ofta den samma. De två texttyperna nchar och varchar använder jag betydligt mer sällan.

Att spara texter i en tabell - 2019-11-05

Serien om tabeller tuffar på. Normalt behövs kolumner innehållande text. Ett vanligt sätt att spara text på är med nvarchar, vilket ger utvecklaren möjlighet att spara det mesta. En viktig sak att tänka på är att inte använda nvarchar när det finns specialanpassade kolumner att spara datan i. Exempelvis bör geografisk data sparas i geography om möjligt. (Mer om olika typer i framtida inlägg.)

Ett vanligt misstag man gör när man skapar nvarchar-kolumner är att man skapar dem för långa. Undvik att skapa dem längre än nödvändigt, eftersom allt för långa kan påverka prestandan. (Mer om prestandaoptimering kommer komma i framtida bloggserier.) Om du känner dig osäker på vilken längd du ska välja så ska du komma ihåg att det är enkelt att utöka längden längre fram om det skulle behövas, se bara på bilden här under.

En viktig fråga är om man bör använda sig utav nvarchar eller varchar. Och mitt korta svar är, är du osäker så kör med nvarchar. En av orsakerna är att nvarchar tillåter fler typer av tecken, något du kan se i bilden här under där varchar tydligt inte tillåter en bokstav i det kyrilliska alfabetet. Så, om du är osäker på vilka tecken som kommer användas eller om du sparar användarinförd data, välj nvarchar.

Vad är då fördelen med att använda sig utav varchar? Jo, den tar enbart upp hälften så mycket plats för samma mängd tecken. Det kan med andra ord förbättra prestandan i specifika fall. Det är dock ett mindre problem idag än tidigare då lagringsutrymme är billigt nu för tiden. De fall där det passar sig väl att använda sig utav varchar är för kolumner som sparar interna texter som man vet inte innehåller ovanliga tecken. Exempelvis om man har en tabell som loggar varje gång någon del av ett system används.

Tabeller är grunden, tider i kolumner - 2019-11-04

Den första bloggpostsserien drar igång med tabeller, vilket är hela grunden i alla SQL Server. Jag har funderat en lång stund och kunde faktiskt inte komma på en vettig databas utan tabeller. Därför börjar vi där. Och när jag har tänkt igenom allt lite mer så kom jag fram till att det faktiskt finns många fler fallgropar än man kan tro. Men innan vi kommer till de lite svårare valen så kommer jag börja med att gå igenom grunden till tabeller, nämligen kolumner.

När man väljer att ha med tider i sin tabell så finns det flera val man måste göra. Det första är att bestämma sig om man behöver både klockslag och datum. Ett vanligt misstag jag ser är att man inte använder sig utav kolumntyperna time och date utan man kör datetime2 för allt. Det är självklart onödigt om man bara använder sig utav datumen eller klockslagen. Så fundera ett extra varv innan du väljer vilken tid du verkligen behöver. Och kom ihåg, behöver du inte sekunder och millisekunder så kan man alltid använda sig utav smalldatetime.

Oftast kommer man fram till att man behöver använda sig utav både datum och klockslag. Och då finns det inte så många val, då är det datetime2 som gäller. Men så enkelt är det inte, eftersom SQL Server tyvärr har en tidstyp till, nämligen datetime. Dock bör man aldrig använda sig utav datetime eftersom den helt enkelt är sämre än datetime2, och datetime finns enbart kvar för backåtkompabilitet. Och jag ska nu demonstrera varför man inte bör använda datetime.

Som du kan se i bilden ovan så har datetime avrundat millisekunderna lite galet. Orsaken till det är att datetime enbart tillåter millisekunder som slutar på 0, 3 och 7. Men datetime2 tillåter att de slutar på valfri siffra, alltså betydligt bättre. Om du nu inte bryr dig om att ha så hög noggrannhet och någon millisekund hit eller dit inte spel någon roll, då kan du med datetime2 välja lägre noggrannhet och därigenom spara 1 bitgrupp (byte).

Första inlägget - 2019-11-02

Detta är mitt första inlägg och jag kommer inte tillhandahålla någon typ av vettig information i detta inlägg. Syftet är mest att se så att allt fungerar. Men om du lyckas hitta hit innan jag har hunnit lägga till något mer så hoppas jag du återvänder inom kort då jag hoppas ha igång bloggen inom en vecka.

Återkommer snart...