¿Por qué IDENTITY_INSERT ON solo está permitido en una tabla a la vez?


20

Es el caso de que IDENTITY_INSERT solo se puede establecer en ON en una tabla de base de datos a la vez, pero ¿por qué? Dado que las IDENTITYcolumnas no son globalmente únicas, no puedo pensar en una situación peligrosa que pueda ser causada al insertar identidades en más de una tabla al mismo tiempo (al menos no más peligroso que generalmente falsificar con IDENTITY INSERT).

IDENTITY INSERT rara vez se debe utilizar, pero ¿cuál es la razón del límite estricto?


1
¿Disuasivo quizás, por lo que rara vez se usa?
Remus Rusanu

@RemusRusanu eso es lo que estaba pensando, ya sea eso o para asegurarme de que no deje accidentalmente II encendido para varias mesas.
Ben Brocka

@Ben, ¿por qué dejarlo encendido accidentalmente para varias mesas es peor que dejarlo encendido accidentalmente para una mesa? Ambos pueden conducir al mismo tipo de problema. Tengo una curiosidad genuina acerca de su pregunta, y no creo que la respuesta sea disuasiva, o tendríamos muchas más restricciones en el motor. Pero sí estoy de acuerdo en que si siente que necesita hacer esto con frecuencia, probablemente haya algo sospechoso.
Aaron Bertrand

@AaronBertrand no lo es, como lo implicaba en la Q. Tampoco estoy seguro acerca de la disuasión, ya que SQL Server permite muchas otras malas prácticas como nombrar sus columnas con palabras clave reservadas (¡a veces incluso si no usa []!)
Ben Brocka

@Ben correcto, eso no fue necesariamente para ti sino para cualquier lector que se haya encontrado con la pregunta.
Aaron Bertrand

Respuestas:


12

Creo que es para hacerlo difícil. Si pudieras dejarlo encendido todo el tiempo, ¿por qué incluso tener un campo de identidad?

Sin embargo, en realidad hay un par de restricciones:

  • Persiste solo en esa conexión
  • Solo se puede configurar en una tabla por conexión

Según las restricciones relacionadas con la conexión, creo que es principalmente así que nunca se deja ENCENDIDO accidentalmente.

Imagínese si alguien activa la inserción de ID en una de sus tablas, ¿entonces no se dio cuenta y se realizó una inserción (normalmente) no válida que rompió la integridad de su campo de ID?

Tenga en cuenta que los campos de ID pueden tener valores duplicados si no hay una restricción o un índice único en su lugar ...


1
+1 Creo que tu último punto sobre los duplicados se pierde por mucho. La gente piensa que si lo establecen IDENTITYtambién se convierte en una restricción única. Muy fácil de refutar, por supuesto, si lo intentan.
Aaron Bertrand

@AaronBertrand Pero, de nuevo, el riesgo de ID duplicado es exactamente el mismo en cualquier tabla con IDENTITY INSERT activado, ¿por qué el límite estricto? Creo que el hecho de que persista solo por la conexión tiene mucho más sentido como precaución.
Ben Brocka

No estaba sugiriendo que el problema de la identificación duplicada fuera una razón del límite estricto.
Aaron Bertrand

6

Supongo que fue una restricción debido a la implementación. Permitir esta configuración en varias tablas fue un éxito potencial:

Dado que este es un parámetro de sesión, permitir que la configuración se active en una sola tabla significa que es un indicador simple y la identificación del objeto de la tabla para almacenar en la sesión, del lado del servidor. Tal vez esto sea solo un número entero: 0 si no hay IDENTITY_INSERT activo, y alguna codificación de databaseid + objectid para la tabla.

Permitir que el parámetro se establezca en varias tablas dentro de una sesión significaría que el servidor almacenaría una lista dinámica de dichos objetos y la verificaría para cada instrucción de inserción. Imagine que una sesión activa el parámetro para mil tablas:

  1. Esto significa que el servidor ha asignado 1000 elementos en la variable de sesión
  2. Esto significa también que el servidor tiene que verificar la lista de los 1000 elementos para cada instrucción de inserción en esta sesión.

También sospecho que set identity_insert on tiene un impacto de rendimiento amplio en el servidor. En Sybase había un " factor de configuración de grabación de identidad ", que permitía guardar el valor del contador de identidad de una tabla para guardarlo solo de vez en cuando (el valor se guarda en la memoria y se escribe en el disco de vez en cuando y en el servidor apagar ). SQL Server se basa en el mismo código, por lo que probablemente tenga una optimización comparable, pero la activación de identity_insert en una tabla probablemente restringe al servidor a guardar el valor de identidad para cada inserción, porque de lo contrario no puede garantizar un tamaño de espacio máximo. Entonces, si una sesión produce un impacto en el rendimiento de las inserciones en una tabla, esto probablemente sea aceptable, pero no si puede hacer que el rendimiento se vea afectado en todas las tablas de aumento automático en el servidor.


+1 Probablemente algo de verdad aquí. No compro el argumento del tamaño de la brecha, ya que solo INSERTpuede estar sucediendo uno a la vez para una sesión, y podría insertar fácilmente 10 millones de IDENTITYvalores codificados .
Aaron Bertrand

El tamaño de la brecha está relacionado con lo que sucede en caso de bloqueo: en Sybase, si el servidor falla, la última identidad se pierde (estaba en la memoria), por lo que se reinicia dejando una brecha (ver factor de configuración de grabación de identidad)
Olivier S

Entonces, en SQL Server, ¿sugiere que sucede algo diferente si el motor se bloquea al insertar 1,000,000 de filas con una columna de identidad o al anular la columna de identidad con 1,000,000 de valores codificados mientras SET IDENTITY_INSERTestá habilitado? Solo estoy sugiriendo que el tamaño de la brecha no afecta a varias tablas de manera diferente de lo que afecta a una sola tabla.
Aaron Bertrand

mi suposición, no tengo absolutamente ninguna prueba de esto, es que SET IDENTITY_INSERT en una tabla fuerza una escritura en disco del autoincremento en cada inserción. La razón sería que, dado que el valor de insertar puede ser cualquier cosa, el servidor no puede considerar "ok, si escribo en el disco sólo una vez cada 1000 filas, en caso de accidente que puede agregar con seguridad 1000 hasta el último valor que salvé"
Olivier S
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.