Mam aplikację, która tworzy miliony tabel w bazie danych SQL Server 2008 (bez klastrów). Chcę uaktualnić do programu SQL Server 2014 (klastrowane), ale po załadowaniu pojawia się komunikat o błędzie:
„W bazie danych znajduje się już obiekt o nazwie„ PK__tablenameprefix__179E2ED8F259C33B ”
Jest to nazwa ograniczenia generowana przez system. Wygląda jak losowo wygenerowana liczba 64-bitowa. Czy to możliwe, że widzę kolizje z powodu dużej liczby tabel? Zakładając, że mam 100 milionów tabel, liczę mniej niż 1-na-1-tryliona szansy na kolizję podczas dodawania kolejnej tabeli, ale to zakłada równomierny rozkład. Czy to możliwe, że SQL Server zmienił algorytm generowania nazw między wersjami 2008 i 2014, aby zwiększyć prawdopodobieństwo kolizji?
Inną znaczącą różnicą jest to, że moja instancja z 2014 r. Jest parą klastrową, ale staram się sformułować hipotezę, dlaczego wygenerowałoby to powyższy błąd.
PS Tak, wiem, że tworzenie milionów stolików jest szalone. To jest kod innej firmy czarnej skrzynki, nad którym nie mam kontroli. Mimo szaleństwa działało w wersji 2008, a teraz nie w wersji 2014.
Edycja: przy bliższej inspekcji generowany sufiks zawsze zaczyna się od 179E2ED8 - co oznacza, że losowa część jest w rzeczywistości tylko liczbą 32-bitową, a prawdopodobieństwo kolizji wynosi zaledwie 1 na 50 za każdym razem, gdy dodawana jest nowa tabela, co jest znacznie bardziej zbliżony do poziomu błędu, który widzę!
Odpowiedzi:
Zależy to od rodzaju ograniczenia i wersji SQL Server.
Przykładowe wyniki 2008
Przykładowe wyniki 2017
W przypadku ograniczeń domyślnych, ograniczeń sprawdzania i ograniczeń klucza obcego ostatnie 4 bajty automatycznie wygenerowanej nazwy są szesnastkową wersją objectid ograniczenia. Ponieważ
objectid
są one gwarantowane jako unikalne, nazwa musi być również unikalna. Również w Sybase te zastosowaniatabname_colname_objectid
W przypadku ograniczeń unikalnych i ograniczeń klucza podstawowego używa Sybase
To także gwarantowałoby wyjątkowość.
SQL Server nie używa tego schematu.
Zarówno w programie SQL Server 2008, jak i 2017 używa 8-bajtowego ciągu na końcu nazwy generowanej przez system, jednak algorytm zmienił sposób generowania ostatnich 4 bajtów.
W 2008 r. Ostatnie 4 bajty reprezentują podpisany licznik liczb całkowitych, który jest przesunięty w stosunku do o
object_id
przez-16000057
dowolne zawijanie wartości ujemnych do maksymalnej liczby całkowitej ze znakiem . (Istotne16000057
jest to, że jest to przyrost stosowany między sukcesywnie tworzonymiobject_id
). To wciąż gwarantuje wyjątkowość.Od 2012 roku w górę nie widzę żadnego wzorca między object_id ograniczenia a liczbą całkowitą uzyskaną przez traktowanie ostatnich 8 znaków nazwy jako szesnastkowej reprezentacji podpisanej liczby int.
Nazwy funkcji na stosie wywołań w 2017 r. Pokazują, że teraz tworzy identyfikator GUID w ramach procesu generowania nazw (w 2008 r. Nie widzę wzmianki o
MDConstraintNameGenerator
). Wydaje mi się, że jest to źródło losowości. Najwyraźniej nie używa całego 16 bajtów z GUID w tych 4 bajtach, które jednak zmieniają się między ograniczeniami.Zakładam, że nowy algorytm został wykonany z jakiegoś powodu ze względu na wydajność kosztem zwiększonej możliwości kolizji w ekstremalnych przypadkach, takich jak Twoja.
Jest to dość patologiczny przypadek, ponieważ wymaga przedrostka nazwy tabeli i nazwy kolumny PK (o ile wpływa to na 8 znaków poprzedzających ostatnie 8), aby były one identyczne dla dziesiątek tysięcy tabel, zanim stanie się prawdopodobne, ale można je całkiem odtworzyć z łatwością poniżej.
Przykład uruchomiony na SQL Server 2017 dla nowo utworzonej bazy danych nie powiódł się w nieco ponad minutę (po utworzeniu 50 931 tabel)
źródło
Pamiętaj, że to jest „ problem urodzinowy ”. Nie próbujesz generować kolizji dla pojedynczego danego skrótu, ale raczej mierzysz prawdopodobieństwo, że żadna z wielu par wartości się nie zderzy.
Tak więc w przypadku N tabel istnieją N * (N-1) / 2 pary, więc tutaj około 10 16 par. Jeśli prawdopodobieństwo zderzenia wynosi 2–64 , prawdopodobieństwo, że pojedyncza para nie zderzy się, wynosi 1-2–64 , ale przy tak wielu parach prawdopodobieństwo braku zderzeń wynosi około ( 1-2–64 ) 10 16 lub więcej jak 1/10 000. Zobacz np. Https://preshing.com/20110504/hash-collision-probabilities/
A jeśli jest to tylko 32-bitowy skrót, prawdopodobieństwo kolizji przekracza 1/2 przy wartościach tylko 77k.
źródło