Una cosa a tener en cuenta es que una clave primaria y un índice agrupado no son lo mismo. Una clave primaria es una restricción y se ocupa de las reglas según las cuales viven los datos (es decir, la integridad de los datos); No tiene nada que ver con la eficiencia / rendimiento. Una clave primaria requiere que las columnas clave sean únicas (en combinación) y NO NULAS (individualmente). Un PK se aplica a través de un índice único, aunque puede estar agrupado o no agrupado.
Un índice agrupado es un medio de ordenar físicamente (es decir, en el disco) los datos en la tabla y se ocupa del rendimiento; No tiene nada que ver con la integridad de los datos. Un índice agrupado puederequieren que las columnas clave sean únicas (en combinación), pero no es necesario. Sin embargo, dado que el índice agrupado es el orden físico de los datos, necesita identificar de manera única cada fila sin importar qué. Entonces, si no lo configura para que requiera unicidad, creará su propia unicidad a través de una columna oculta de "byte" de 4 bytes. Esa columna siempre está allí en índices agrupados no únicos, pero no ocupa espacio cuando los campos clave son únicos (en combinación). Para ver de primera mano cómo funciona esta columna de "uniquifier" (tanto en el índice agrupado como en el efecto sobre los índices no agrupados), consulte este script de prueba que publiqué en PasteBin: script T-SQL para probar el tamaño del Uniquifier .
Por lo tanto, la pregunta principal de:
¿Sería más eficiente agregar un id
campo de incremento automático y usarlo junto con company_id
la clave principal, o agregaría una sobrecarga innecesaria?
está combinando esos dos conceptos, por lo que deben abordarse por separado, aunque definitivamente hay cierta superposición.
¿Debería IDENTITY
agregarse una columna o sería una sobrecarga innecesaria?
Si agrega una INT IDENTITY
columna y la usa para crear una PK, suponiendo que sea una PK agrupada, eso agrega 4 bytes a cada fila. Esta columna es visible y utilizable en consultas. Se podría añadirse a otras tablas como una clave externa, aunque en este caso particular, que no va a ocurrir.
Si no agrega la INT IDENTITY
columna, no puede crear una PK en esta tabla. Sin embargo, aún puede crear un índice agrupado en la tabla siempre que no utilice la UNIQUE
opción. En este caso, SQL Server agregará una columna oculta llamada "uniquifier" que se comporta como se describe anteriormente. Debido a que la columna está oculta, no se puede usar en consultas o como referencia para claves externas.
En lo que respecta a la eficiencia, estas opciones son más o menos las mismas. Sí, habrá un poco menos de espacio al tener el índice agrupado no único debido a que algunas filas (aquellas con los valores de clave únicos iniciales) ocupan 0 bytes, mientras que todas las filas en IDENTITY
/ PK ocuparán los 4 bytes. Pero no habrá suficientes filas de 0 bytes (especialmente con la pequeña cantidad de filas esperadas) para notar una diferencia, y mucho menos que la conveniencia de poder usar la ID
columna en las consultas.
INT IDENTIDAD ¿Columna o hash de org_path
columna computada persistente?
Dado que no buscará filas en función de los org_path
valores, entonces no tiene sentido agregar la sobrecarga de la columna calculada persistente más la necesidad de calcular ese hash en las consultas para que coincida con la columna calculada (esta fue mi sugerencia original, disponible en el historial de revisiones aquí , que se basó en la redacción inicial / detalles de la Pregunta). En este caso particular, la INT IDENTITY
columna "ID" es probablemente la mejor.
Orden de columna clave
Dado que la ID
Columna rara vez, si alguna vez, se usará en consultas, y dado que los dos casos de uso principales son obtener "todas las filas" o "todas las filas para un determinado company_id
", crearía el PK en company_id, id
. Y debido a que esto significa que las filas no se insertan secuencialmente, especificaría una FILLFACTOR
de 90. También deberá asegurarse de realizar un mantenimiento de índice regular para reducir la fragmentación.
Segunda pregunta
¿El hecho de que company_id sea la clave principal en otra tabla tiene algún efecto aquí?
No.
Desencadenar
Dado que los org_path
valores dentro de a company_id
son únicos, aún debe crear un activador INSERT, UPDATE
para hacer cumplir esto. En el activador, haga un IF EXISTS
con una consulta que probablemente haga un COUNT(*)
y GROUP BY company_id, org_path
. Si se encuentra algo, emita un ROLLBACK
para cancelar la operación DML y luego un RAISERROR
dicho que hay duplicados.
Colación
En mi respuesta inicial (basada en la redacción original / detalles escasos de la pregunta, y disponible en el historial de revisiones aquí ), sugerí que posiblemente se use una intercalación binaria (es decir, _BIN2
). Ahora que tenemos una idea de qué org_path
es exactamente , no recomendaría usar una intercalación binaria. Dado que no habrá signos diacríticos, que no desea hacer uso de equivalencias lingüísticas.
¿Por qué necesitas una PK?
¿Por qué no simplemente ir con company_id como un índice no agrupado?
Dijiste que la mayoría de las búsquedas están en todas las entradas o por company_id.
Rara vez se actualizan.
Rara vez se borra
org_path, esta es la única tabla en la que existe.
La respuesta de Martin Smith puede darle lo que necesita
No estoy familiarizado con agregar automáticamente un unificador de enteros de 4 bytes Tal
vez me falta algo, pero si no tiene otras columnas indexadas, entonces no veo ningún propósito en este caso de uso
Si le preocupa DRI, las tablas deben usar la tabla Compañía como FK para company_id
fuente
INCLUDE
columna, pero eso es aún peor, ya que simplemente duplica la tabla. Es cierto que el PK no es necesario; La parte importante es el índice agrupado. Pero una vez que tenga la IDENTIDAD, bien podría ir con PK. Y por favor vea el nuevo enlace en mi respuesta para un recorrido en Uniquifier 😃