sql >> Databasteknik >  >> RDS >> Sqlserver

Ska jag designa en tabell med en primärnyckel av varchar eller int?

När du väljer primärnyckeln väljer du vanligtvis också den klustrade nyckeln. De två är ofta förvirrade, men du måste förstå skillnaden.

Primära nycklar är logiska affärer element. Den primära nyckeln används av din applikation för att identifiera en enhet, och diskussionen om primärnycklar handlar till stor del om att använda naturliga nycklar eller surrogatnyckel. Länkarna går in i mycket mer detalj, men grundidén är att naturliga nycklar härleds från en befintlig entitetsegenskap som ssn eller phone number , medan surrogatnycklar inte har någon som helst betydelse med hänsyn till affärsenheten, som id eller rowid och de är vanligtvis av typen IDENTITY eller någon sorts uuid. Min personliga åsikt är att surrogatnycklar är överlägsna naturliga nycklar, och valet bör alltid vara identitetsvärden för endast lokala applikationer, guider för alla slags distribuerade data. En primärnyckel ändras aldrig under entitetens livstid.

Klustrade nycklar är nyckeln som definierar den fysiska lagringen av rader i tabellen. De flesta gånger överlappar de primärnyckeln (den logiska enhetsidentifieraren), men det verkställs inte eller krävs. När de två är olika betyder det att det finns ett icke-klustrat unikt index på tabellen som implementerar primärnyckeln. Klustrade nyckelvärden kan faktiskt ändras under radens livstid, vilket resulterar i att raden fysiskt flyttas i tabellen till en ny plats. Om du måste separera den primära nyckeln från den klustrade nyckeln (och ibland gör du det), är det betydligt svårare att välja en bra klustrad nyckel än att välja en primärnyckel. Det finns två primära faktorer som driver din klustrade nyckeldesign:

  1. Det vanliga dataåtkomstmönstret .
  2. Lagringsöverväganden .

Dataåtkomstmönster . Med detta förstår jag hur tabellen efterfrågas och uppdateras. Kom ihåg att klustrade nycklar bestämmer den faktiska ordningen för raderna i tabellen. För vissa åtkomstmönster gör vissa layouter stor skillnad i världen när det gäller frågehastighet eller för att uppdatera samtidighet:

  • aktuella kontra arkivdata. I många applikationer är data som hör till den aktuella månaden ofta åtkomliga, medan den tidigare sällan nås. I sådana fall använder tabelldesignen tabellpartitionering efter transaktionsdatum, ofta med hjälp av en glidande fönsteralgoritm. Den aktuella månadspartitionen hålls på filgruppen som ligger på en het snabbdisk, den arkiverade gamla data flyttas till filgrupper på billigare men långsammare lagring. Uppenbarligen i detta fall är den klustrade nyckeln (datum) inte den primära nyckeln (transaktions-id). Separationen av de två drivs av skalkraven, eftersom frågeoptimeraren kommer att kunna upptäcka att frågorna bara är intresserade av den aktuella partitionen och inte ens tittar på de historiska.

  • Bearbetning av FIFO-köstil. I det här fallet har bordet två hot spots:svansen där insättningar sker (enqueue) och huvudet där borttagningar sker (dequeue). Den klustrade nyckeln måste ta hänsyn till detta och organisera tabellen för att fysiskt separera svans- och huvudplatsen på disken, för att tillåta samtidighet mellan enqueue och dequeue, t.ex. genom att använda en köordernyckel. I ren köer denna klustrade nyckel är den enda nyckeln, eftersom det inte finns någon primärnyckel i tabellen (den innehåller meddelanden , inte entiteter ). Men de flesta gånger är kön inte ren, den fungerar också som lagring för enheterna och linjen mellan kön och tabellen är suddig. I det här fallet finns det också en primärnyckel, som inte kan vara den klustrade nyckeln:entiteter kan återställas i kö, vilket ändrar klustrade nyckelvärde för köordningen, men de kan inte ändra det primära nyckelvärdet. Att inte se separationen är den främsta anledningen till att köer med stöd av användartabeller är så notoriskt svåra att få till rätta och fulla av dödlägen:eftersom kö och avkö inträffar interfolierade genom bordet, istället för att lokaliseras till köens bakkant och huvud.

  • Korrelerad bearbetning. När applikationen är väldesignad kommer den att dela upp bearbetning av korrelerade objekt mellan dess arbetstrådar. Till exempel är en processor designad för att ha 8 arbetartrådar (säg att matcha de 8 processorerna på servern) så att processorerna partitionerar data mellan sig, t.ex. arbetare 1 plockar bara upp konton som heter A till E, arbetare 2 F till J etc. I sådana fall bör tabellen faktiskt klustras av kontonamnet (eller av en sammansatt nyckel som har den första bokstaven i kontonamnet längst till vänster), så att arbetare lokaliserar sina frågor och uppdateringar i tabellen. Ett sådant bord skulle ha 8 distinkta hot spots, runt området varje arbetare koncentrerar sig för tillfället, men det viktiga är att de inte överlappar varandra (ingen blockering). Den här typen av design är utbredd på OLTP-designer med hög genomströmning och i TPCC benchmark-laddningar, där denna typ av partitionering också återspeglas i minnesplatsen för sidorna som laddas i buffertpoolen (NUMA-lokalitet), men jag avviker.

Lagringsöverväganden . Den klustrade nyckeln bredd har enorma återverkningar i förvaringen av bordet. För det första tar nyckeln plats på varje sida som inte är blad i b-trädet, så en stor nyckel kommer att uppta mer utrymme. För det andra, och ofta viktigare, är att den klustrade nyckeln används som uppslagsnyckel av alla icke-klustrade nyckel, så varje icke-klustrade nyckel måste lagra hela bredden av den klustrade nyckeln för varje rad. Det är detta som gör stora klustrade nycklar som varchar(256) och vägleder dåliga val för klustrade indexnycklar.
Också valet av nyckel har inverkan på klustrade indexfragmentering, vilket ibland drastiskt påverkar prestandan.

Dessa två krafter kan ibland vara antagonistiska, dataåtkomstmönstret kräver en viss stor klustrad nyckel som kommer att orsaka lagringsproblem. I sådana fall behövs naturligtvis en balans, men det finns ingen magisk formel. Du mäter och du testar för att komma till sweet spot.

Så vad gör vi av allt detta? Börja alltid med att överväga klustrade nyckel som också är primärnyckeln i formen entity_id IDENTITY(1,1) NOT NULL . Separera de två och organisera tabellen därefter (t.ex. partition efter datum) när det är lämpligt.



  1. Hur får jag SQLSRV-tillägget att fungera med PHP, eftersom MSSQL är utfasat?

  2. Finns det ett alternativ till TOP i MySQL?

  3. SQL FOREIGN KEY Begränsning:The Ultimate, Easy Guide för nybörjare

  4. Vad är Oracle Database?