sql >> Databáze >  >> RDS >> Sqlserver

Mám navrhnout tabulku s primárním klíčem varchar nebo int?

Při výběru primárního klíče obvykle volíte také sdružený klíč. Ti dva jsou často zmatení, ale musíte pochopit rozdíl.

Primární klíče jsou logické podnikání Prvky. Primární klíč používá vaše aplikace k identifikaci entity a diskuse o primárních klíčích je z velké části o tom, zda použít přirozené klíče nebo náhradní klíč. Odkazy jdou do mnohem více podrobností, ale základní myšlenkou je, že přirozené klíče jsou odvozeny z existující vlastnosti entity, jako je ssn nebo phone number , zatímco náhradní klíče nemají s ohledem na obchodní entitu žádný význam, například id nebo rowid a obvykle jsou typu IDENTITY nebo nějaký druh uuid. Můj osobní názor je, že náhradní klíče jsou lepší než přirozené klíče a výběr by měl být vždy hodnot identity pro pouze místní aplikace, vodítka pro jakýkoli druh distribuovaných dat. Primární klíč se během existence entity nikdy nemění.

Skupinové klíče jsou klíčem, který definuje fyzické uložení řádků v tabulce. Většinou se překrývají s primárním klíčem (identifikátor logické entity), ale to není ve skutečnosti vynuceno ani vyžadováno. Když se tyto dva liší, znamená to, že v tabulce existuje jedinečný index bez klastrů, který implementuje primární klíč. Hodnoty seskupených klíčů se mohou ve skutečnosti během životnosti řádku změnit, což vede k fyzickému přesunutí řádku v tabulce do nového umístění. Pokud musíte oddělit primární klíč od seskupeného klíče (a někdy to uděláte), je výběr dobrého seskupeného klíče podstatně těžší než výběr primárního klíče. Existují dva primární faktory, které řídí váš návrh clusterového klíče:

  1. Převládající vzorec přístupu k datům .
  2. Aspekty úložiště .

Vzor přístupu k datům . Tím rozumím způsobu, jakým je tabulka dotazována a aktualizována. Pamatujte, že seskupené klíče určují skutečné pořadí řádků v tabulce. U určitých vzorů přístupu mají některá rozvržení největší světový rozdíl, pokud jde o rychlost dotazů nebo souběžnost aktualizace:

  • aktuální vs. archivní data. V mnoha aplikacích se často přistupuje k datům aktuálního měsíce, zatímco k datům v minulosti se přistupuje zřídka. V takových případech používá návrh tabulky rozdělení tabulky podle data transakce, často pomocí algoritmu posuvného okna. Oddíl aktuálního měsíce je uchováván ve skupině souborů umístěné na rychlém disku, archivovaná stará data se přesouvají do skupin souborů hostovaných na levnějším, ale pomalejším úložišti. Je zřejmé, že v tomto případě není seskupený klíč (datum) primárním klíčem (ID transakce). Oddělení těchto dvou je řízeno požadavky na škálování, protože optimalizátor dotazů bude schopen zjistit, že dotazy se zajímají pouze o aktuální oddíl a ani se nedívají na ty historické.

  • Zpracování ve stylu fronty FIFO. V tomto případě má tabulka dvě aktivní místa:konec, kde dochází k vkládání (zařazení do fronty), a záhlaví, kde dochází k odstranění (odstranění fronty). Seskupený klíč to musí vzít v úvahu a uspořádat tabulku tak, aby fyzicky oddělil umístění konce a hlavy na disku, aby se umožnila souběžnost mezi enqueue a dequeue, např. pomocí klíče objednávky ve frontě. V čistém fronty tento seskupený klíč je jediný klíč, protože v tabulce není žádný primární klíč (obsahuje zprávy , nikoli entity ). Ale většinou není fronta čistá, funguje také jako úložiště pro entity a čára mezi frontou a tabulku je rozmazaný. V tomto případě existuje také primární klíč, kterým nemůže být klastrovaný klíč:entity mohou být znovu zařazeny do fronty, čímž se změní hodnota klastrovaného klíče pořadí pořadí zařazení do fronty, ale nemohou změnit hodnotu primárního klíče. Neschopnost vidět oddělení je primárním důvodem, proč je tak notoricky obtížné najít správné fronty podporované tabulkou uživatelů a protkané uváznutím:protože fronta a fronta se vyskytují prokládané tabulkou, místo toho, aby byly lokalizovány na konci a v čele fronty.

  • Korelované zpracování. Když je aplikace dobře navržena, rozdělí zpracování korelovaných položek mezi svá pracovní vlákna. Například procesor je navržen tak, aby měl 8 pracovních vláken (řekněme, aby odpovídalo 8 CPU na serveru), takže procesory mezi sebou rozdělují data, např. pracovník 1 přebírá pouze účty s názvem A až E, pracovník 2 F až J atd. V takových případech by měla být tabulka ve skutečnosti seskupená podle názvu účtu (nebo pomocí složeného klíče, který má první písmeno názvu účtu úplně vlevo), aby pracovníci lokalizovali své dotazy a aktualizace v tabulce. Takový stůl by měl 8 odlišných hot spots, kolem plochy se v daný moment soustředí každý pracovník, ale důležité je, že se nepřekrývají (žádné blokování). Tento druh návrhu převládá u vysoce propustných návrhů OLTP a při načítání benchmarků TPCC, kde se tento druh rozdělení také odráží v umístění paměti stránek načtených ve fondu vyrovnávací paměti (lokalita NUMA), ale to odbočím.

Úložiště . šířka seskupeného klíče má obrovské odezvy při ukládání stolu. Za prvé klíč zabírá místo na každé jiné stránce b-stromu, takže velký klíč zabere více místa. Za druhé, a často důležitější, je, že seskupený klíč je používán jako vyhledávací klíč každým neklastrovaným klíčem, takže každý neklastrovaný klíč bude muset uložit celou šířku seskupeného klíče pro každý řádek. To je důvod, proč jsou velké seskupené klíče jako varchar(256) a vodítka špatná volba pro seskupené indexové klíče.
Také výběr klíče má dopad na fragmentaci seskupeného indexu, někdy drasticky ovlivňuje výkon.

Tyto dvě síly mohou být někdy antagonistické, vzor přístupu k datům vyžaduje určitý velký sdružený klíč, což způsobí problémy s úložištěm. V takových případech je samozřejmě nutná rovnováha, ale neexistuje žádný kouzelný vzorec. Měříte a testujete, abyste se dostali na sladké místo.

Co z toho všeho tedy uděláme? Vždy začněte uvažováním seskupeného klíče, který je zároveň primárním klíčem ve tvaru entity_id IDENTITY(1,1) NOT NULL . Oddělte je a podle potřeby uspořádejte tabulku (např. rozdělení podle data).



  1. Představujeme běžné tabulkové výrazy v SQL Server

  2. 3 způsoby, jak získat seznam databází v SQL Server (T-SQL)

  3. mysql_fetch_assoc():zadaný argument není platným zdrojem výsledků MySQL v php

  4. Úvod do Multi-Statement Table-Valued Functions (MSTVF) v SQL Server