trešdiena, 2011. gada 12. oktobris

SQL Server uniqueidentifier datu tips

Globāli unikāli identifikatori (bieži dēvēti kā "GUID") SQL Server datu bāzē tiek glabāti kā datu tips "uniqueidentifier". Šis datu tips ir ar plusiem un arī mīnusiem.

Galvenais plus ir tas, ka unikālie identifikatori ir unikāli- neviens dators uz pasaules neuzģenerēs tādu pašu vērtību (jo ģenerējot vērtību tiek izmantots tīkla kartes numurs, kas ir unikāls. ja nav tīkla kartes, tad skatīt atlikušo rindkopas daļu vai šeit). Un arī uz viena datora nepārtraukti ģenerējot jaunas vērtības, to iespēja atkārtoties ir tik tuva nullei, ka uzskata, ka tas nav iespējams.

Unikāli identifikatori SQL Server datu bāzē tiek glabāti kā bitu virkne (kopumā 16 baiti).  Bet parasti tos attēlo kā 36 simbolus garu teksta virkni, piemēram:
07C9F1EE-5723-4190-AFC9-83FA2F2618D7
Ja izņemam mīnus-zīmes un sadalām 16 baitus 32 daļās (katrai 4 biti) attēlojot katras daļas heksadecimālo vērtību, iegūstam šo attēlojumu. Jāņem vērā, ka šis ir tikai attēlojums. Unikālie identifikatori nav teksta virkne! Tātad, lai tos salīdzinātu ar tekstu, tie no sākuma ir jākonvertē uz teksta datu tipu.

Jaunu unikālu identifikatoru datu bāzē var izveidot izmantojot NEWID() funkciju (kādreiz var pamēģināt dabūt divas vienādas vērtības):
Select NEWID()
Var izmantot arī citu funkciju: NEWSEQUENTIALID(). Šī funkcija var tikt izmantota tikai kā noklusētās vērtības ierobežojums tabulai (vairāk msdn). Šīs funkcijas pluss ir tāds, ka tiek ģenerēti unikālie identifikatori augošā secībā.

Tagad vēl citi apsvērumi ("+" un "-") lietojot šo datu tipu:
  • "+" Sistēmās, kur ieraksti rodas no dažādiem avotiem un kurām ir jāspēj pēc tam atrast to radītais ieraksts, unikālie identifikatori ir lielisks kandidāts primārai atslēgai. Piemēram, ja ir online/offline sistēma, kur ieraksti tiek radīti abos režīmos, unikālie identifikatori nodrošina, ka vēlāk nav konflikti. Automātiski ģenerēti skaitliski identifikatori šeit nederēs.
  • "-" Atšķirīgs veids kā strādāt ar datu bāzi (nevar izmanot kā identity kolonnu). Parasti gan šeit risinājums ir visai vienkāršs- kolonnas vērtība tiek radīta uz datora, kurā tiek ģenerēts ieraksts.
    .Net Guid ģenerēšanai:
    "Guid mansGuid = Guid.NewGuid();"
    .Net Guid no teksta:
    "Guid mansGuid2 = Guid.Parse("D4B38FEA-8436-43E7-BA34-AE638AE68CFF");"
  • "-" Cilvēkam šādu identifikatoru ir grūti atcerēties, ievadīt. Praktiski neviens cits kā tikai dators negribēs ar šādu datu tipu strādāt.
  • "-" Datu bāzē ar šo tipu strādāt kā primāro atslēgu ir daudzi lieli mīnusi
    • Aizņem 16 baitus, tātad, ja tā ir primārā atslēga un indekss- salīdzinoši liels apjoms (indeksu izmērs). Tas pats int aizņem tikai 4 baitus, bet var saglabāt -2^63 -2^31 (-2,147,483,648) līdz pat 2^31 - 1 (2,147,483,647) vērtības!
    • NEWID()- Tiek ģenerēti izmantojot algoritmu, kas nekādā veidā nepakļaujas secībai. Salīdzinot katru nākamo ģenerēto vērtību, tā var būt gan lielāka, gan mazāka. Respektīvi, ģenerētās vērtības izskatās/ir pilnīgi nejaušas. No tā izriet:
      • Nevar noteikt secību, kādā tie ir ģenerēti;
      • Nav veidu, kā piešķirt papildus nozīmi vērtībai, kā vien to, ka tā ir unikāla;
      • Dati tiek ievietoti tabulā dažādās vietās (ja šī vērtība ir klasterētais indeks), izsaucot datu defragmentāciju (par ko daudz tiku rakstījis šajā emuārā, Indeksu fragmentācija). Tas visādā ziņā palielina slodzi un ir slikti.
    • NEWSEQUENTIALID()- ģenerē unikālos identifikatorus augošā secībā, bet tikai līdz brīdim, kad tiek pārstartēts dators. Pēc pārstartēšanas atkal visas ģenerētās vērtības ir augošā secībā, bet salīdzinoši ar iepriekš ģenerētajām var būt mazākas.
    No tā visa lielais secinājums ir- unikālajiem identifikatoriem ir viens milzīgs pluss un arī daudzi mīnusi. Lai kā, tos, kas ģenerēti izmantojot NEWID() vai rodas dažādās vietās (dažādiem datoriem),  nevajadzētu izmantot kā klasterēto indeksu. Un ja tomēr no tā nekādi neizvairīties- jāņem vērā "maksa" par to.

    Papildus var lasīt msdn šeit un šeit.

    Nav komentāru:

    Ierakstīt komentāru