Tabele fără cheie primară

Am mai multe tabele ale căror date unice reprezintă o coloană de identificator unic (o Guid). Deoarece ghidurile nu sunt secvențiale (și sunt generate de către client astfel încât nu pot folosi newsequentialid ()), am făcut un index non-primar, ne-clustered pe acest câmp de identificare, mai degrabă decât să dau tabele o primare clusterială cheie.

Mă întreb ce înseamnă implicațiile de performanță pentru această abordare. Am văzut că unii oameni sugerează că tabelele ar trebui să aibă o valoare de auto-incrementare ("identitate") int ca o cheie primară clustită, chiar dacă aceasta nu are nici un sens, deoarece înseamnă că motorul bazei de date poate să utilizeze acea valoare rapid căutați un rând în loc să trebuiască să utilizați un marcaj.

Baza de date mea este replicată în fuzionare pe o mulțime de servere, așa că am eliminat coloanele de identitate int, deoarece sunt puțin păroase pentru a ajunge repede.

Care sunt gandurile tale? Ar trebui tabelele să aibă chei primare? Sau este bine să nu aveți indici clusteri dacă nu există coloane sensibile care să fie indexate în acest fel?

0
fr hi bn
Din moment ce faceți replicarea, identitățile dvs. corecte sunt ceva de care trebuie să vă îndepărtați. Mi-ar face ca GUID-ul dvs. să fie o cheie primară, dar neschimbată, deoarece nu puteți folosi newsequentialid. Asta mi se pare cel mai bun curs. Dacă nu faceți un PK, dar puneți un indice unic pe acesta, mai devreme sau mai târziu, acest lucru poate determina persoanele care întrețin sistemul să nu înțeleagă relațiile FK introducând corect erori.
adăugat autor HLGEM, sursa

7 răspunsuri

Cheia primară are trei scopuri:

  • indică faptul că coloana (coloanele) trebuie să fie unică
  • indică faptul că coloana (coloanele) ar trebui să fie non-null
  • documentați intenția că acesta este identificatorul unic al rândului

Primele două pot fi specificate în multe moduri, așa cum ați făcut deja.

Al treilea motiv este bun:

  • pentru oameni, astfel încât să poată vedea cu ușurință intenția dvs.
  • pentru computer, astfel încât un program care ar putea compara sau prelucra altceva tabelul dvs. poate interoga baza de date pentru cheia primară a tabelului.

O cheie primară nu trebuie să fie un câmp cu număr automat de auto-creștere, așadar aș spune că este o idee bună să specificați coloana guid ca cheie primară.

0
adăugat
@MattHamilton re "... nu este o idee bună să aveți o coloană guid ca cheie primară, deoarece cheile primare sunt grupate și ghidurile sunt aleatoare" pentru a depăși acest lucru, puteți utiliza funcția "newsequentialid ()" pe SQL 2005/2008 editați: a găsit postarea CodingHorror care vorbește despre acest lucru ;-)
adăugat autor Leon Bambrick, sursa
Cu siguranță nu este o idee bună să aveți o coloană guid ca o cheie primară, deoarece cheile primare sunt grupate și ghidurile sunt aleatoare. Asta inseamna ca ori de cate ori inserati un nou rand, tabela dvs. este in esenta restructurata pe disc. Oamenii recomandă în mod normal ca cheile primare să fie secvențiale, în continuă creștere, astfel încât fiecare rând nou să fie atașat la sfârșitul mesei.
adăugat autor Matt Hamilton, sursa
O cheie primară este în mod prestabilit susținută de un index grupat, dar poate fi eliminat (indexul grupat).
adăugat autor Andrei Rînea, sursa

O cheie primară nu trebuie să fie un câmp de autoincrementare, în multe cazuri acest lucru înseamnă doar că complicați structura tabelului.

În schimb, o cheie primară ar trebui să fie colecția minimă de atribute (rețineți că majoritatea DBMS va permite o cheie primară compusă) care identifică în mod unic o tuplă.

În termeni tehnici, ar trebui să fie domeniul în care orice alt domeniu al tuplei este complet dependent de funcționalitate. (Dacă nu este posibil să trebuiască să se normalizeze).

În practică, problemele de performanță ar putea însemna că fuzionați tabele și folosiți un câmp incremental, dar mi se pare că amintesc ceva despre optimizarea prematură fiind rău ...

0
adăugat

De asemenea, am auzit intotdeauna ca intarirea automata este buna pentru performanta, chiar daca nu o folositi.

0
adăugat

Din moment ce faceți replicarea, identitățile dvs. corecte sunt ceva de care trebuie să vă îndepărtați. Mi-ar face ca GUID-ul dvs. să fie o cheie primară, dar neschimbată, deoarece nu puteți folosi newsequentialid. Asta mi se pare cel mai bun curs. Dacă nu faceți un PK, dar puneți un indice unic pe acesta, mai devreme sau mai târziu, acest lucru poate determina persoanele care întrețin sistemul să nu înțeleagă relațiile FK introducând corect erori.

0
adăugat

Doar să intru, pentru că Matt ma bătut puțin.

Trebuie să înțelegeți că, deși un index cluster este pus pe tasta primară a unui tabel în mod implicit, cele două concepte sunt separate și ar trebui luate în considerare separat. Un CIX indică modul în care datele sunt stocate și menționate de către NCIX-urile, în timp ce PK oferă o unicitate pentru fiecare rând pentru a satisface cerințele LOGICE ale unui tabel.

Un tabel fără CIX este doar o grămadă. Un tabel fără PK este adesea considerat "nu un tabel". Este mai bine să înțelegeți atât conceptele PK, cât și cele CIX separat, astfel încât să puteți lua decizii sensibile în proiectarea bazei de date.

jefui

0
adăugat

Nimeni nu a răspuns la întrebarea reală: ce sunt plusurile / minusurile unui tabel cu NO PK NOR și un index CLUSTERED. În opinia mea, dacă optimizați pentru inserții mai rapide (mai ales inserarea în vrac în mărime, de exemplu, atunci când încărcați în vrac date într-o masă care nu este gol), un astfel de tabel: cu indice NO clustered, NO constrângeri, NU cheia primară, într-o bază de date cu model de recuperare simplă, este cea mai bună. Acum, dacă doriți vreodată să interogați acest tabel (spre deosebire de scanarea acestuia în întregime), este posibil să doriți să adăugați un index non-clustered non-unic, după cum este necesar, dar să-i păstrați la minim.

0
adăugat
De fapt, aceasta este greșită - așa cum arată clar Kimberly Tripp (Regina de indexare): cu indexul bun creat crește performanța INSERT! sqlskills.com/BLOGS/KIMBERLY/post/…
adăugat autor marc_s, sursa
N-aș spune că se va arăta în mod clar :) Vorbește despre principii generale, fără a-și susține declarația cu nimic, în timp ce vorbesc despre un scenariu foarte specific pe care l-am întâlnit în practica mea: inserări vaste ale potențialelor sute de milioane de înregistrări într-o tabelă ne-goală, care nu este niciodată actualizată sau accesată într-un mod aleatoriu citit, ci scanată în întregime. Presupun că ar putea exista mai mulți factori în joc decât indici. Întotdeauna testați-vă copiii cu optimizări.
adăugat autor zvolkov, sursa

Atunci când se ocupă cu indexuri, trebuie să determinați ce va fi folosit pentru tabel. Dacă introduceți în primul rând 1000 de rânduri o secundă și nu faceți nicio interogare, atunci un index cluster este o lovitură la performanță. Dacă faci 1000 de interogări pe secundă, atunci nu ai un index va duce la performanțe foarte proaste. Cel mai bun lucru pe care trebuie să-l faceți când încercați să acordați interogări / indici este să utilizați Analizorul planului de interogare și SQL Profiler în SQL Server. Acest lucru vă va arăta unde vă aflați în scanări de masă costisitoare sau alte blocante de performanță.

În ceea ce privește argumentul GUID vs ID, puteți găsi persoane online care jură pe ambele. Întotdeauna am fost învățat să utilizez GUID-uri, cu excepția cazului în care am un motiv foarte bun să nu. Jeff are un post bun care vorbește despre motivele utilizării GUID-urilor: http: //www.codinghorror .com / blog / arhive / 000817.html .

Ca și în cazul a mai multor dezvoltări legate de orice, dacă căutați să îmbunătățiți performanța, nu există un singur răspuns corect. Depinde într-adevăr de ceea ce încercați să realizați și de modul în care implementați soluția. Singurul răspuns adevărat este să testați, să testați și să testați din nou metricile de performanță pentru a vă asigura că vă atingeți obiectivele.

[Editați | ×] @Matt, după ce am făcut mai multe cercetări despre dezbaterea GUID / ID, am dat peste acest post. După cum am menționat mai devreme, nu există un răspuns corect sau corect. Depinde de nevoile dvs. specifice de implementare. Dar acestea sunt câteva motive destul de valide pentru a utiliza GUID-urile ca cheie primară:

De exemplu, există o problemă cunoscută sub numele de "hotspot", în care anumite pagini de date dintr-un tabel se află sub o părere de valută relativ ridicată. Practic, ceea ce se întâmplă este cea mai mare parte a traficului pe o masă (și, prin urmare, la nivel de pagină încuietori) apare pe o mică parte a mesei, spre sfârșitul anului. Noile înregistrări vor merge întotdeauna la acest hotspot, deoarece IDENTITY este un generator de secvențiale de numere. Aceste inserții sunt dificile deoarece necesită blocare exclusivă a paginii pe pagina în care sunt adăugate (hotspot-ul). Acest lucru serializează efectiv toate inserțiile la o masă grație mecanismului de blocare a paginilor. NewID (), pe de altă parte, nu suferă de hotspoturi. Valorile generate folosind funcția NewID() sunt doar secvențiale pentru bursele scurte de inserturi (unde funcția este apelată foarte repede, cum ar fi în timpul inserării cu mai multe rânduri), ceea ce face ca rândurile introduse să se răspândească aleatoriu pe paginile de date ale tabelului din toate la sfârșitul - eliminând astfel un hotspot din inserturi.

     

De asemenea, deoarece inserțiile sunt repartizate aleatoriu, șansele de împărțire a paginilor sunt mult reduse. În timp ce o pagină divizată aici și acolo nu este prea rău, efectele se adaugă rapid. Cu IDENTITY, pagina Fill Factor este destul de inutilă ca un mecanism de tuning și ar putea fi setat la 100% - rândurile nu vor fi introduse niciodată în nicio pagină decât în ​​ultima. Cu NewID (), puteți utiliza de fapt Fill Factor ca instrument de performanță. Puteți seta factorul de umplere la un nivel care aproximează creșterea estimată a volumului dintre refacerea indexului și apoi programați reconstrucțiile în timpul orelor în afara orelor de vârf folosind dbcc reindex. Acest lucru întârzie efectiv hit-urile de performanță ale împărțirii paginilor până în momentele în afara orelor de vârf.

     

Dacă chiar și cred că este posibil să fie necesar să activați replicarea pentru tabelul în cauză - atunci este posibil să faceți din PK un identificator unic și să semnați câmpul guid ca ROWGUIDCOL. Replicarea va necesita un câmp guid unic de valoare cu acest atribut și va adăuga unul dacă nu există. Dacă există un câmp corespunzător, atunci acesta va folosi doar cel care există acolo.

     

Un alt beneficiu uriaș pentru utilizarea GUID-urilor pentru PK-uri este faptul că valoarea este într-adevăr garantată unică - nu doar între toate valorile generate de serverul acest , ci toate valorile generate de toate computere - fie că este serverul dvs. db, serverul web, serverul de aplicații sau clientul. Destul de mult, fiecare limbă modernă are capacitatea de a genera un guid valabil acum - în .NET puteți folosi System.Guid.NewGuid. Acest lucru este FOARTE la îndemână atunci când se ocupă cu seturi de date master-detaliate memorate în cache, în special. Nu trebuie să angajezi scheme nebunești temporare de chei pentru a-ți face o legătură înainte de a fi comise. Purtați doar un Guid nou perfect valid din sistemul de operare pentru valoarea cheie permanentă a fiecărei noi înregistrări în momentul creării înregistrării.

     

http://forums.asp.net/t/264350.aspx

0
adăugat
Fascinant. Voi examina opțiunea "împărțirea paginilor și indexarea refuzurilor" dacă performanța devine o problemă. Mulțumesc pentru că.
adăugat autor Matt Hamilton, sursa
Citiți GUIDs as Primary și / sau cheia de grupare și Spațiu pe disc este ieftin - asta e NOT punctul! și multe altele din postările sale excelente pe blog - ea în mod clar arată cât de rău este ideea unei chei de grupare pe un GUID coloana este. De asemenea, hotspoturile sunt un mit care sunt mult timp dezvăluit - nu mai este o problem
adăugat autor marc_s, sursa