Чому IDENTITY_INSERT ON дозволений лише на одному столі одночасно?


20

Ідеально, що IDENTITY_INSERT може бути встановлено на УВІМКНЕННЯ лише в одній таблиці бази даних одночасно, але чому? Оскільки IDENTITYстовпці не є унікальними у всьому світі, я не можу придумати жодної небезпечної ситуації, яка могла б бути викликана вставкою ідентифікацій у більш ніж одну таблицю одночасно (принаймні, не небезпечніше, ніж загальне зіграння з IDENTITY INSERT).

Ідентифікаційну вставку слід застосовувати рідко, але в чому причина жорсткої межі?


1
Можливо, стримуючий характер, тому його рідко використовують?
Рем Русану

@RemusRusanu - це те, про що я думав, або щоб переконатися, що ви випадково не залишите II ON для декількох таблиць.
Бен Брокка

@Ben, чому залишати його випадково для декількох таблиць гірше, ніж випадково залишати його випадково для однієї таблиці? Обидва можуть призвести до однакового питання. Мені по-справжньому цікаво ваше питання, і я не вважаю, що стримування є відповіддю, інакше у нас буде набагато більше обмежень у роботі двигуна. Але я згоден, що якщо вам здається, що вам потрібно часто це робити, можливо, є щось підозріле.
Аарон Бертран

@AaronBertrand це не так, як я мав на увазі в Q. Не впевнений і в стримуванні, оскільки SQL Server дозволяє безліч інших поганих практик, таких як називання ваших стовпців зарезервованими ключовими словами (іноді навіть якщо ви не використовуєте []!)
Бен Брока

@Ben right, це не обов'язково для вас, але для будь-якого читача, який стикався з цим питанням.
Аарон Бертран

Відповіді:


12

Я думаю, що це зробити це важко. Якщо ви могли просто залишати його весь час, навіщо навіть мати поле ідентичності?

Однак насправді є кілька обмежень:

  • Він зберігається лише на цьому зв'язку
  • Він встановлюється лише на одній таблиці за з'єднання

Виходячи з обмежень, пов’язаних із підключенням, я думаю, що це в основному так, що ніколи випадково не залишається ввімкнено.

Уявіть собі, якщо хтось увімкнув вставку ідентифікатора на одній із ваших таблиць, ви цього не зрозуміли, і виконано (як правило) недійсну вставку, яка порушила цілісність вашого поля ідентифікатора?

Майте на увазі, що поля ідентифікаторів можуть мати повторювані значення, якщо на місці немає обмеження або унікального індексу ...


1
+1 Я думаю, що ваш останній пункт про дублікати пропущено багато. Люди думають, що якщо вони встановлять IDENTITYце, також стає унікальним обмеженням. Дуже легко спростувати, звичайно, якщо вони хоч спробують.
Аарон Бертран

@AaronBertrand Але знову ж таки, повторюваний ідентифікаційний ризик точно такий же, як у будь-якій таблиці, на якій встановлено IDENTITY INSERT, чому жорсткий ліміт? Я вважаю, що той факт, що він зберігається лише підключення, має набагато більше сенсу як запобіжний засіб.
Бен Брокка

Я не припускав, що проблема дублювання ідентифікатора є причиною жорсткого обмеження.
Аарон Бертран

6

Я здогадуюсь, що це було обмеження внаслідок реалізації. Дозволити це налаштування на кількох столах було потенційним враженням від ефективності:

Оскільки це параметр сеансу, дозволяючи активувати налаштування на одній таблиці, це означає, що це простий прапор та ідентифікатор об'єкта таблиці для зберігання на сеансі на стороні сервера. Можливо, це лише одне ціле число: 0, якщо жоден IDENTITY_INSERT не активний, і деяке кодування databaseid + objectid для таблиці.

Дозволити встановлення параметра в декількох таблицях протягом сеансу означатиме, що сервер буде зберігати динамічний список таких об'єктів і перевіряти його на кожне оператор вставки. Уявіть, що сеанс активує параметр для тисячі таблиць:

  1. Це означає, що сервер виділив 1000 елементів у змінній сесії
  2. Це також означає, що сервер повинен перевіряти список 1000 елементів для кожного оператора вставки в цьому сеансі.

Також я підозрюю, що встановлення ident_insert увімкнено ефективність на сервері. У sybase був " фактор набору ідентичності запису ", який дозволив зберегти значення лічильника ідентичності таблиці, що зберігається лише один раз (значення зберігається в пам'яті та записується на диск раз у раз і на сервер закрити ). SQL Server базується на одному і тому ж коді, тому, ймовірно, має порівнянну оптимізацію, але активація ідентифікатора_інсерту в таблиці, ймовірно, обмежує сервер зберігати значення ідентичності для кожної вставки, тому що в іншому випадку він не може гарантувати максимальний розмір проміжку. Отже, якщо один сеанс робить показник продуктивності для вставок в одну таблицю, це, ймовірно, прийнятно, але ні, якщо він може зробити хіт perf у всіх таблицях auto_increment на сервері ..


+1 Напевно, тут є якась правда. Я не купую аргумент розміру розриву, оскільки INSERTза час сеансу може тривати лише один , і я міг легко вставити 10 мільйонів твердо кодованих IDENTITYзначень.
Аарон Бертран

Розмір розриву пов'язаний з тим, що відбувається в разі збоїв: на sybase, якщо сервер виходить з ладу, остання ідентифікація втрачається (це було в пам'яті), тому він перезапускається, залишаючи пробіл (див. Множину спалювання встановленого фактора)
Olivier S

Отже, у SQL Server ви припускаєте, що щось інше відбувається, якщо двигун виходить з ладу, вставляючи 1 000 000 рядків із стовпцем ідентичності, або переосмислюючи стовпець ідентичності на 1 000 000 твердо кодованих значень при SET IDENTITY_INSERTввімкненому? Я просто припускаю, що розмір проміжку не впливає на кілька таблиць інакше, ніж на одну таблицю.
Аарон Бертран

я здогадуюсь - я не маю абсолютно ніяких доказів цього - це те, що SET IDENTITY_INSERT на столі примушує записувати на диск автоматичне збільшення на кожній вставці. Обґрунтуванням було б те, що оскільки введене вами значення може бути будь-яким, сервер не може вважати «добре, якщо я пишу на диск лише раз на 1000 рядків, у випадку збою я можу сміливо додавати 1000 до останнього збереженого значення»
Олів'є S
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.