Dlaczego IDENTITY_INSERT ON jest dozwolony tylko na jednym stole na raz?

20

Jest tak, że IDENTITY_INSERT można ustawić na ON tylko w jednej tabeli bazy danych na raz, ale dlaczego? Ponieważ IDENTITYkolumny nie są globalnie unikatowe, nie mogę wymyślić żadnej niebezpiecznej sytuacji, która mogłaby być spowodowana wstawieniem tożsamości do więcej niż jednej tabeli w tym samym czasie (przynajmniej nie bardziej niebezpieczna niż ogólnie fudowanie z WSTAWKĄ TOŻSAMOŚCI).

WSTAWKA TOŻSAMOŚCI powinna być rzadko używana, ale jaki jest powód sztywnego limitu?

Ben Brocka
źródło
1
Może odstraszający, więc jest rzadko używany?
Remus Rusanu,
@RemusRusanu to jest to, co myślałem, albo to, albo aby upewnić się, że przypadkowo nie zostawisz II WŁĄCZONE dla wielu stołów.
Ben Brocka
@Ben dlaczego pozostawienie go włączonego przypadkowo na wielu stołach jest gorsze niż przypadkowe pozostawienie włączonego na jednym stole? Oba mogą prowadzić do tego samego rodzaju problemu. Naprawdę jestem ciekawa twojego pytania i nie sądzę, że odpowiedzią jest odstraszanie, bo inaczej mielibyśmy o wiele więcej ograniczeń w silniku. Ale zgadzam się, że jeśli czujesz, że musisz to robić często, prawdopodobnie jest coś podejrzanego.
Aaron Bertrand
@AaronBertrand to nie jest, jak sugerowałem w Q. Nie jestem pewien co do odstraszania, ponieważ SQL Server pozwala na wiele innych złych praktyk, takich jak nazywanie kolumn zastrzeżonymi słowami kluczowymi (czasami nawet jeśli nie używasz []!)
Ben Brocka
@Ben prawo, które niekoniecznie było dla ciebie, ale dla każdego czytelnika, który napotkał pytanie.
Aaron Bertrand

Odpowiedzi:

12

Myślę, że to utrudnia. Jeśli możesz pozostawić to cały czas włączone, to po co w ogóle mieć pole tożsamości?

Istnieje jednak kilka ograniczeń:

  • Utrzymuje się tylko na tym połączeniu
  • Można to ustawić tylko na jednym stole na połączenie

W oparciu o ograniczenia związane z połączeniem, myślę, że jest to głównie dlatego nigdy nie zostaje przypadkowo WŁĄCZONE.

Wyobraź sobie, że jeśli ktoś włączył wstawkę identyfikacyjną na jednej z twoich tabel, nie zdawałeś sobie sprawy i wykonano (normalnie) nieprawidłową wstawkę, która złamała integralność twojego pola identyfikacyjnego?

Pamiętaj, że pola ID mogą mieć zduplikowane wartości, jeśli nie ma ograniczenia lub unikalnego indeksu ...

JNK
źródło
1
+1 Myślę, że bardzo brakuje twojego ostatniego punktu na temat duplikatów. Ludzie myślą, że jeśli to ustalą, stanie się IDENTITYto również wyjątkowym ograniczeniem. Oczywiście bardzo łatwo je obalić, jeśli spróbują.
Aaron Bertrand
@AaronBertrand Ale ponownie, ryzyko duplikatu ID jest dokładnie takie samo w każdej tabeli z WŁĄCZONYM TOŻSAMOŚCIM, dlaczego twardy limit? Myślę, że fakt, że utrzymuje się tylko dla połączenia, ma o wiele większy sens jako środek ostrożności.
Ben Brocka
Nie sugerowałem, że problem z duplikatem identyfikatora był przyczyną twardego limitu.
Aaron Bertrand
6

Domyślam się, że było to ograniczenie ze względu na wdrożenie. Dopuszczenie tego ustawienia na wielu stołach było potencjalnym hitem wydajności:

Ponieważ jest to parametr sesji, zezwolenie na aktywację ustawienia w pojedynczej tabeli oznacza, że ​​jest to prosta flaga i identyfikator obiektu tabeli do przechowywania w sesji po stronie serwera. Może to tylko jedna liczba całkowita: 0, jeśli nie jest aktywne IDENTITY_INSERT, i pewne kodowanie databaseid + objectid dla tabeli.

Zezwolenie na ustawienie parametru w wielu tabelach w ramach sesji oznaczałoby, że serwer przechowywałby dynamiczną listę takich obiektów i sprawdzałby ją dla każdej instrukcji insert. Wyobraź sobie, że sesja aktywuje parametr tysiąca tabel:

  1. Oznacza to, że serwer przydzielił 1000 elementów w zmiennej sesji
  2. Oznacza to również, że serwer musi sprawdzić listę 1000 pozycji dla każdej instrukcji insert w tej sesji.

Podejrzewam również, że ustawienie Włożona tożsamość ma wpływ na wydajność na serwerze. W sybase istniał „ współczynnik nagrywania tożsamości ”, który pozwalał na zapisanie wartości licznika tożsamości tabeli, która ma być zapisywana tylko raz na jakiś czas (wartość jest przechowywana w pamięci i zapisywana na dysk raz na jakiś czas i na serwerze zamknąć ). Program SQL Server jest oparty na tym samym kodzie, więc prawdopodobnie ma pewną porównywalną optymalizację, ale aktywacja identy- fikacji_wstawienia w tabeli prawdopodobnie ogranicza serwer do zapisywania wartości tożsamości dla każdej wstawki, ponieważ w przeciwnym razie nie może zagwarantować maksymalnego rozmiaru przerwy. Więc jeśli jedna sesja spowoduje poprawę wydajności na wstawkach w jednej tabeli, jest to prawdopodobnie dopuszczalne, ale nie, jeśli może sprawić, że perf trafi we wszystkie tabele auto_increment na serwerze ..

Olivier S.
źródło
+1 Prawdopodobnie tutaj jest trochę prawdy. Nie kupuję argumentu dotyczącego wielkości luki, ponieważ tylko jedna INSERTmoże być wykonywana jednocześnie na sesję, i z łatwością mogę wstawić 10 milionów IDENTITYwartości zakodowanych na stałe.
Aaron Bertrand
Rozmiar luki jest powiązany z tym, co dzieje się w przypadku awarii: na serwerze Sybase, jeśli serwer ulegnie awarii, ostatnia tożsamość zostanie utracona (znajdowała się w pamięci), więc restartuje się, pozostawiając lukę (patrz współczynnik ustawienia spalania tożsamości)
Olivier S
Czy w SQL Server sugerujesz, że dzieje się coś innego, jeśli silnik ulegnie awarii podczas wstawiania 1 000 000 wierszy z kolumną tożsamości, czy też zastępujesz kolumnę tożsamości z 1 000 000 wartości zakodowanych na stałe, gdy SET IDENTITY_INSERTjest włączony? Po prostu sugeruję, że rozmiar luki nie wpływa na wiele tabel inaczej niż na pojedynczą tabelę.
Aaron Bertrand
zgaduję - nie mam absolutnie żadnych dowodów na to - że SET IDENTITY_INSERT na stole wymusza zapis na dysk przyrostu automatycznego na każdej wkładce. Uzasadnieniem byłoby to, że ponieważ wstawiana wartość może być dowolna, serwer nie może uznać „ok, jeśli zapisuję na dysk tylko raz na 1000 wierszy, w przypadku awarii mogę bezpiecznie dodać 1000 do ostatniej zapisanej wartości”
Olivier S