Po przerwie związanej ze świętami, mam nadzieję, że blog wróci do dawnej formy… 🙂
W bazach danych wykorzystuje się zwykle jako wartości kluczy głównych i obcych liczby całkowite – INT.
Drugim podejściem (mniej popularnym) jest wykorzystanie globalnych identyfikatorów GUID. Jaka jest tak naprawdę różnica? Skupmy się na zaletach i wadach każdego z nich.
Zaczynamy od typów całkowitych (int).
Zalety:
-bardzo mały rozmiar (tylko 4 bajty),
-naturalna postać – każdy kolejny wiersz to sekwencja liczb naturalnych,
-identyfikator ostatnio dodanego wiersza można łatwo uzyskać za pomocą IDENTITY lub SCOPE_IDENTITY.
Wady:
-problemy ze scalaniem tych samych tabel znajdujących się w różnych bazach. Gdy każda z tabeli ma osobny licznik, ciężko będzie scalić wiersze – prawdopodobnie będą występować duplikaty,
-powyższa wada utrudnia pracę w bazach rozproszonych,
-trudno wygenerować kolejną wartość po stronie klienta i mieć pewność, że w przypadku commit’u nie będzie duplikatu.
Zalety GUID:
-łatwość scalania,
-doskonały do tabel\baz rozproszonych,
-identyfikator jest unikalny w całym systemie.
Wady:
-zbyt pamięciożerny – 16 bajtów! Jeśli na prawdę potrzebujemy tyle wartości lepiej wykorzystać BIGINT i mieć pewność, że cała pula będzie bezpiecznie zaalokowana (unikalna),
-nie możemy wykorzystać IDENTITY\SCOPE_IDENTITY, które często znaczącą ułatwiają życie,
-generując ID po stronie klienta (częsty przypadek) nie mamy pewności unikalności – zależy to od systemu a nawet sprzętu!,
-ostatnia, największa wada to fragmentacja.
Fragmentacja w bazach danych to zdecydowanie temat na osobny post lub nawet cykl postów. Aby zrozumieć problem wyobraźmy sobie, że mamy listę imion np.
Anna
Piotr
Paweł
Marek
Marcin
…
Następnie tworzymy indeks clustered na tej kolumnie. Oznacza to, że dane do bazy danych musza być dodawane w formie posortowanej. Tzn Anna musi zostać dodana przed Piotr, Paweł przed Piotr itd – zgodnie z alfabetem. Dodając więc kolejno wiersz Anna a następnie Piotr, system musi zaalokować ileś pamięci między Anna a Piotr aby było miejsce na imiona znajdujące się pomiędzy nimi. Jeśli zabraknie tego miejsca występuje fragmentacja – puste miejsca, przepisania. Fragmentacja tworzy się również podczas usuwania wierszy. Oczywiście w realnym systemie SQL Server sytuacja jest bardziej skomplikowana – przykład miał tylko naszkicować problem.
Jak to się ma więc do GUID? Są one niestety niesekwencyjne.Generując kolejno dwa GUID’y nie możemy przewidzieć ich kolejności. W przypadku int (IDENTITY) jest to bardzo proste – każda kolejna liczba jest większa.
Podsumowując, największym problemem GUID’a jest szeroko pojęta wydajność (pamięć, kosztowne operacje spowodowane fragmentacją bazy). Osobiście uważam, że o ile nie wykorzystujemy baz rozproszonych, lepiej nie korzystać z GUID’ów – szybszym i bardziej naturalnym typem jest INT\BIGINT.
Podoba mi się. Krótko i na temat.
Można coś wspomnieć o wykorzystaniu GUID’ów w aplikacjach internetowych, np zabezpieczanie sesji.
Nie jestem tylko pewien do fragmentu:
“generując ID po stronie klienta (częsty przypadek) nie mamy pewności unikalności”
Czy ktoś zna takie przypadki?
Czy w bazach rozproszonych GUID’y mogą być generowane niezależnie?
Generowanie GUID’a na podstawie konfiguracji powinno ten problem zmniejszać.
“Generując ID po stronie klienta (częsty przypadek) nie mamy pewności unikalności.”
Takie ID jest ważne tylko do momentu kiedy robimy Inserta do bazy, wtedy zostanie ono napisane prawdziwym ID wygenerowanym przez bazę.
teoretycznie GUID to GUID i nie powinno dojść do takiej sytuacji, że 2 różne maszyny (nawet ta sama) generują takie same GUIDy
Guid zawsze może być sekwencyjny.
Wtedy unikasz problemu z fragmentacją indeksów.
@KOTO,@Anonimowy
Może się przytrafić duplikat. Jest to jednak małe prawdopodobne ale teoretycznie jak najbardziej możliwe. Moim zdaniem zwłaszcza jeśli wykorzystywane są różne maszyny. Polecam:http://www.4guysfromrolla.com/webtech/110806-1.shtml
“In creating very large databases, GUIDs (as generated by MS’s NEWID() function) WILL have collisions, or duplicates. In a previous project where I was building a large Customer ODS (Operational Data Store), I typically found about 4 collisions per million rows. Code has to be developed to handle this. This was in SQL Server 2000. Perhaps SQL Server 2005 has remedied this.”
@Sylwek:
System.Guid sekwencyjny?Jak?