En mis bases de datos, tiendo a adquirir el hábito de tener una clave primaria de entero de incremento automático con el nombre id
de cada tabla que hago para tener una búsqueda única para cualquier fila en particular.
¿Se considera esto una mala idea? ¿Hay algún inconveniente en hacerlo de esta manera? A veces tendré múltiples índices como id, profile_id, subscriptions
dónde id
está el identificador único, profile_id
enlaces al exterior id
de una Profile
tabla, etc.
¿O hay escenarios en los que no desea agregar dicho campo?
t
, y el activo 120 a la vezt + 60
. Si puede ver ambas ID (100 y 120) en forma no ofuscada, ahora sabe la cantidad total de activos que existen, así como aproximadamente la tasa a la que se crean. Esta es la fuga de información. Esto no es puramente hipotético.Respuestas:
Nunca es una mala idea tener un identificador de fila único garantizado. Supongo que no debería decir nunca, pero vamos con la abrumadora mayoría del tiempo, es una buena idea.
Las desventajas potenciales teóricas incluyen un índice adicional para mantener y el espacio de almacenamiento adicional utilizado. Esa nunca ha sido una razón suficiente para no usar una.
fuente
TableName.id
a diferencia deTableName.TableName_id
, porque ¿a qué más seid
referirá eso ? Si tengo otro campo de identificación en la tabla, lo prefijo con un nombre de tabla si se refiere a otra tablaWITHOUT ROWID
tablas (con un explícitoPRIMARY KEY
) como una optimización. Pero de lo contrario, unaINTEGER PRIMARY KEY
columna es un alias para el rowid.No estoy de acuerdo con todas las respuestas anteriores. Hay muchas razones por las cuales es una mala idea agregar un campo de incremento automático en todas las tablas.
Si tiene una tabla donde no hay claves obvias, un campo de incremento automático parece una buena idea. Después de todo, no quieres
select * from blog where body = '[10000 character string]'
. Que prefieresselect * from blog where id = 42
. Yo diría que en la mayoría de estos casos, lo que realmente quieres es un identificador único; No es un identificador único secuencial. Probablemente desee utilizar un identificador universalmente único en su lugar.Hay funciones en la mayoría de las bases de datos para generar identificadores únicos aleatorios (
uuid
en mysql, postgres.newid
En mssql). Estos le permiten generar datos en múltiples bases de datos, en diferentes máquinas, en cualquier momento, sin conexión de red entre ellos, y aun así fusionar datos con cero conflictos. Esto le permite configurar más fácilmente múltiples servidores e incluso centros de datos, como por ejemplo, con microservicios.Esto también evita que los atacantes adivinen las URL de las páginas a las que no deberían tener acceso. Si hay un
https://example.com/user/1263
probablemente también hay unhttps://example.com/user/1262
. Esto podría permitir la automatización de una vulnerabilidad de seguridad en la página de perfil de usuario.También hay muchos casos en los que una columna de líquido es inútil o incluso dañina. Digamos que tienes una red social. Hay una
users
mesa y unafriends
mesa. La tabla de amigos contiene dos columnas de ID de usuario y un campo de incremento automático. Desea3
ser amigo5
, así que inserte3,5
en la base de datos. La base de datos agrega una identificación de incremento automático y almacena1,3,5
. De alguna manera, el usuario3
vuelve a hacer clic en el botón "Agregar amigo". Si inserta3,5
nuevamente en la base de datos, la base de datos agrega una identificación de incremento automático e inserta2,3,5
. Pero ahora3
y5
son amigos entre sí dos veces! Eso es una pérdida de espacio, y si lo piensas, también lo es la columna de incremento automático. Todo lo que necesitas para ver sia
yb
son amigos es seleccionar para la fila con esos dos valores. Son, juntos, un identificador de fila único. (Probablemente quieras escribir algo de lógica para asegurarte3,5
y que5,3
sean deduplicados).Todavía hay casos en los que los ID secuenciales pueden ser útiles, como cuando se construye un acortador de url, pero en su mayoría (e incluso con el acortador de url) lo que realmente desea usar es un ID único generado aleatoriamente.
TL; DR: use UUID en lugar de incremento automático, si aún no tiene una forma única de identificar cada fila.
fuente
Las claves autoincementales tienen principalmente ventajas.
Pero algunos posibles inconvenientes podrían ser:
Aquí hay una sección de artículo de Wikipedia sobre las desventajas de las claves sustitutas.
fuente
Solo para ser contrario, no, NO necesita tener siempre una PK de AutoInc numérica.
Si analiza sus datos cuidadosamente, a menudo identifica claves naturales en los datos. Este suele ser el caso cuando los datos tienen un significado intrínseco para el negocio. A veces, las PK son artefactos de sistemas antiguos que los usuarios comerciales utilizan como segundo idioma para describir los atributos de su sistema. He visto los números VIN del vehículo utilizados como la clave principal de una tabla "Vehículo" en un sistema de gestión de flota, por ejemplo.
Sin embargo, se originó, SI ya tiene un identificador único, úselo. No cree una segunda clave primaria sin sentido; Es un desperdicio y puede causar errores.
A veces puede usar un AutoInc PK para generar un valor significativo para el cliente, por ejemplo, Números de política. Establecer el valor inicial en algo sensato y aplicar reglas comerciales sobre ceros a la izquierda, etc. Este es probablemente el enfoque de "lo mejor de ambos mundos".
Cuando tenga un pequeño número de valores que son relativamente estáticos, use valores que tengan sentido para el usuario del sistema. ¿Por qué usar 1,2,3 cuando puede usar L, C, H donde L, H y C representan vida, automóvil y hogar en un contexto de "Tipo de póliza" de seguro o, volviendo al ejemplo de VIN, qué tal usar "TO "para Toyota? Todos los autos Toyata tienen un VIN que comienza "TO". Es una cosa menos para que los usuarios recuerden, hace que sea menos probable que introduzcan errores de programación y de usuario e incluso puede ser un sustituto utilizable para una descripción completa en los informes de administración que simplifica los informes. para escribir y tal vez más rápido para generar.
Un desarrollo adicional de esto es probablemente "un puente demasiado lejos" y generalmente no lo recomiendo, pero lo estoy incluyendo por completo y puede que le resulte útil. Es decir, use la Descripción como clave principal. Para los datos que cambian rápidamente, esto es una abominación. Para datos muy estáticos que se informan en todo el tiempo , tal vez no. Solo lo menciono para que esté allí como una posibilidad.
SÍ uso AutoInc PK, solo engancho mi cerebro y busco mejores alternativas primero. El arte del diseño de bases de datos está haciendo algo significativo que se puede consultar rápidamente. Tener demasiadas uniones dificulta esto.
EDITAR Otro caso crucial en el que no necesita una PK autogenerada es el caso de las tablas que representan la intersección de otras dos tablas. Para seguir con la analogía del automóvil, un automóvil tiene 0..n accesorios, cada accesorio se puede encontrar en muchos automóviles. Para representar esto, debe crear una tabla Car_Accessory que contenga las PK de Car and Accessory y otra información relevante sobre las fechas del enlace, etc.
Lo que no necesita (generalmente) es un AutoInc PK en esta tabla: solo se podrá acceder a través del automóvil "dígame qué accesorios hay en este automóvil" o desde el Accesorio "dígales qué automóviles tienen este accesorio"
fuente
Don't create a second, meaningless primary key; it's wasteful and may cause errors.
Sin embargo, si la forma de establecer la unicidad para un registro es una combinación de 6 columnas, entonces unirse a las 6 todo el tiempo es muy propenso a errores en sí mismo. Los datos, naturalmente, tienen un PK, pero es mejor usar unaid
columna y una restricción única en esas 6 columnas.Muchas tablas ya tienen una identificación única natural. No agregue otra columna de identificación única (incremento automático o de otro modo) en estas tablas. Utilice la identificación única natural en su lugar. Si agrega otra identificación única, esencialmente tiene una redundancia (duplicación o dependencia) en sus datos. Esto va en contra de los principios de normalización. Una identificación única depende de la otra para la precisión. Esto significa que deben mantenerse perfectamente sincronizados en todo momento en cada sistema que gestione estas filas. Es solo otra fragilidad en la integridad de sus datos que realmente no desea tener que administrar y validar a largo plazo.
La mayoría de las tablas en estos días realmente no necesitan el impulso de rendimiento muy menor que daría una columna de identificación única adicional (y a veces incluso perjudica el rendimiento). Como regla general en TI, ¡evite la redundancia como la peste! Resístalo en todas partes que te sugieran. Es anatema. Y preste atención a la cita. Todo debe ser lo más simple posible, pero no más simple. No tenga dos identificadores únicos donde uno sea suficiente, incluso si el natural parece menos ordenado.
fuente
En sistemas más grandes, la ID es un refuerzo de consistencia, úselo casi en cualquier lugar. En este contexto, NO se recomiendan las claves primarias individuales, son caras en el resultado final (lea por qué).
Cada regla tiene una excepción, por lo que es posible que no necesite un ID de incremento automático de enteros en las tablas de preparación utilizadas para la exportación / importación y en tablas similares de un solo sentido o tablas temporales. También preferiría GUID en lugar de ID en sistemas distribuidos.
Muchas respuestas aquí sugieren que se debe tomar una clave única existente. Bueno, incluso si tiene 150 caracteres? No lo creo.
Ahora mi punto principal:
Parece que los opositores de la identificación de entero de incremento automático están hablando de pequeñas bases de datos con hasta 20 tablas. Allí pueden permitirse un enfoque individual para cada mesa.
PERO una vez que tenga un ERP con más de 400 tablas, tener una ID de incremento automático en cualquier lugar (excepto los casos mencionados anteriormente) tiene mucho sentido. No confíe en otros campos únicos, incluso si están presentes y asegurados para ser únicos.
JOIN
tablas, sin necesidad de verificar cuáles son las claves.En sistemas más grandes, puede valer la pena ignorar los beneficios menores de esas claves primarias individuales y usar de manera consistente la identificación de incremento automático en la mayoría de los casos. El uso de campos únicos existentes como claves primarias puede estar ahorrando algunos bytes por registro, pero el almacenamiento adicional o el tiempo de indexación no plantean ningún problema en los motores de bases de datos actuales. En realidad, está perdiendo mucho más dinero y recursos en el tiempo perdido de los desarrolladores / mantenedores. El software actual debe optimizarse para el tiempo y el esfuerzo de los programadores: qué enfoque con identificaciones consistentes cumple mucho mejor.
fuente
No es una buena práctica hacer diseños superfluos. Es decir, no es una buena práctica tener siempre una clave primaria de incremento automático int cuando no se necesita.
Veamos un ejemplo donde no se necesita uno.
Tiene una tabla para artículos: tiene una clave primaria int
id
y una columna varchar denominadatitle
.También tiene una tabla llena de categorías de artículos:
id
clave primaria int, varcharname
.Una fila en la tabla Artículos tiene un
id
5 y untitle
"Cómo cocinar ganso con mantequilla". Desea vincular ese artículo con las siguientes filas en su tabla de categorías: "Fowl" ( id : 20), "Goose" ( id : 12), "Cooking" ( id : 2), "Butter" (id: 9) .Ahora tiene 2 tablas: artículos y categorías. ¿Cómo se crea la relación entre los dos?
Podría tener una tabla con 3 columnas: id (clave principal), article_id (clave externa), category_id (clave externa). Pero ahora tienes algo como:
Una mejor solución es tener una clave primaria que se compone de 2 columnas.
Esto se puede lograr haciendo:
Otra razón para no utilizar un entero de incremento automático es si está utilizando UUID para su clave principal.
Los UUID son, por definición, únicos, lo que logra lo mismo que usar enteros únicos. También tienen sus propios beneficios adicionales (y contras) sobre los enteros. Por ejemplo, con un UUID, usted sabe que la cadena única a la que se refiere apunta a un registro de datos en particular; Esto es útil en los casos en que no tiene 1 base de datos central, o donde las aplicaciones tienen la capacidad de crear registros de datos fuera de línea (luego subirlos a la base de datos en una fecha posterior).
Al final, no debes pensar en las claves primarias como una cosa. Debe pensar en ellos como la función que realizan. ¿Por qué necesitas claves primarias? Para poder identificar de forma exclusiva conjuntos específicos de datos de una tabla utilizando un campo que no se cambiará en el futuro. ¿Necesita una columna en particular llamada
id
para hacer esto, o puede basar esta identificación única en otros datos (inmutables)?fuente
Seguro.
En primer lugar, hay bases de datos que no tienen aumentos automáticos (por ejemplo, Oracle, que ciertamente no es uno de los contendientes más pequeños). Esto debería ser una primera indicación de que no a todos les gustan o los necesitan.
Más importante, piense en qué es realmente la ID : es una clave principal para sus datos. Si tiene una tabla con una clave primaria diferente, entonces no necesita una ID y no debe tenerla. Por ejemplo, una tabla
(EMPLOYEE_ID, TEAM_ID)
(donde cada empleado puede estar en varios equipos al mismo tiempo) tiene una clave primaria claramente definida que consiste en esas dos ID. Agregar unaID
columna de autoincremento , que también es una clave principal para esta tabla, no tendría ningún sentido. Ahora está cargando 2 claves primarias, y la primera palabra en "clave primaria" debería darle una pista de que realmente debería tener solo una.fuente
Usualmente uso una columna de "identidad" (entero de incremento automático) cuando defino nuevas tablas para datos "de larga duración" (registros que espero insertar una vez y mantener indefinidamente incluso si terminan "eliminados lógicamente" configurando un campo de bits )
Hay algunas situaciones en las que puedo pensar cuando no desea usarlas, la mayoría de las cuales se reducen a escenarios en los que una tabla en una instancia de la base de datos no puede ser la fuente autorizada para los nuevos valores de ID:
Hay soluciones alternativas que permiten el uso de columnas de identidad en estas situaciones, como he mencionado anteriormente, pero en la mayoría de ellas, la actualización de la columna de enteros de identidad a un GUID es más simple y resuelve el problema más completamente.
fuente
ID, ID_M, ID_N
) debido a que adjunta propiedades a instancias de su relación M: N.Una clave primaria con incremento automático (identidad) es una buena idea, excepto para observar que no tiene sentido fuera del contexto de la base de datos y los clientes inmediatos de esa base de datos. Por ejemplo, si transfiere y almacena algunos de los datos en otra base de datos, luego proceda a escribir datos diferentes en ambas tablas de la base de datos, los identificadores divergirán, es decir, los datos con un identificador de 42 en una base de datos no necesariamente coincidirán con los datos con un id de 42 en el otro.
Dado esto, si es necesario poder identificar filas de manera exclusiva fuera de la base de datos (y con frecuencia lo es), entonces debe tener una clave diferente para este propósito. Una clave comercial cuidadosamente seleccionada servirá, pero a menudo terminará en una posición de una gran cantidad de columnas necesarias para garantizar la unicidad. Otra técnica es tener una columna Id como una clave primaria agrupada de incremento automático y otra columna de identificador único (guid) como una clave única no agrupada, con el fin de identificar de forma única la fila donde sea que exista en el mundo. La razón por la que todavía tiene una clave de incremento automático en este caso es porque es más eficiente agrupar e indexar la clave de incremento automático que hacer lo mismo con un guid.
Un caso en el que es posible que no desee una clave de incremento automático sería una tabla de muchos a muchos, donde la clave principal es un compuesto de las columnas Id de otras dos tablas (aún podría tener una clave de incremento automático aquí, pero yo no veo el punto de eso).
Otra pregunta es el tipo de datos de la clave de incremento automático. El uso de un Int32 le brinda un rango de valores grande pero relativamente limitado. Personalmente, con frecuencia utilizo columnas bigint para el Id, para prácticamente nunca tener que preocuparme por la falta de valores.
fuente
Como otras personas han defendido una clave principal incremental, crearé una para un GUID:
Editar: punto duplicado
fuente
Como principio del buen diseño, cada tabla debe tener una forma confiable de identificar de forma única una fila. Aunque para eso sirve una clave primaria, no siempre requiere la existencia de una clave primaria. Agregar una clave primaria a cada tabla no es una mala práctica ya que proporciona una identificación de fila única, pero puede ser innecesaria.
Para mantener relaciones confiables entre las filas de dos o más tablas, debe hacerlo mediante claves externas, de ahí la necesidad de claves primarias en al menos algunas tablas. Agregar una clave principal a cada tabla hace que sea más fácil extender el diseño de su base de datos cuando llega el momento de agregar nuevas tablas o relaciones a los datos existentes. Planear con anticipación siempre es algo bueno.
Como principio básico (quizás una regla difícil), el valor de una clave primaria nunca debería cambiar durante la vida de su fila. Es aconsejable suponer que cualquier dato comercial en una fila está sujeto a cambios a lo largo de su vida útil, por lo que cualquier dato comercial será un mal candidato para una clave primaria. Esta es la razón por la cual algo abstracto como un entero auto-incrementado es a menudo una buena idea. Sin embargo, los enteros autoincrementados tienen sus limitaciones.
Si sus datos solo tendrán vida dentro de su base de datos, los enteros con incremento automático están bien. Pero, como se ha mencionado en otras respuestas, si alguna vez desea que sus datos se compartan, se sincronicen o tengan una vida fuera de su base de datos, los enteros con incremento automático son claves primarias deficientes. Una mejor opción será un guid (también conocido como uuid "id universalmente único").
fuente
La pregunta, y muchas de las respuestas, pierden el punto importante de que todas las claves naturales para cada tabla residen únicamente en el esquema lógico de la base de datos, y todas las claves sustitutas para cada tabla residen únicamente en el esquema físico de la base de datos. otras respuestas analizan únicamente los beneficios relativos de las claves sustitutas de enteros frente a GUID, sin analizar las razones por las cuales las claves sustitutas se utilizan correctamente y cuándo.
Por cierto: evitemos el uso del término mal definido e impreciso clave principal . Es un artefacto de modelos de datos pre-relacionales que primero fue cooptado (imprudentemente) en el modelo relacional, y luego cooptados nuevamente en el dominio físico por varios proveedores de RDBMS. Su uso solo sirve para confundir la semántica.
Tenga en cuenta del modelo relacional que, para que el esquema lógico de la base de datos esté en la primera forma normal , cada tabla debe tener un conjunto de campos visibles para el usuario, conocido como clave natural, que identifique de forma única cada fila de la tabla. En la mayoría de los casos, esta clave natural se identifica fácilmente, pero en ocasiones se debe construir, ya sea como un campo de desempate o de otra manera. Sin embargo, dicha clave construida siempre es visible para el usuario y, por lo tanto, siempre reside en el esquema lógico de la base de datos.
Por el contrario, cualquier clave sustituta en una tabla reside únicamente en el esquema físico de la base de datos (y, por lo tanto, siempre debe ser completamente invisible para los usuarios de la base de datos, por razones de seguridad y para el mantenimiento de la integridad de la base de datos). La única razón para introducir una clave sustituta es abordar los problemas de rendimiento en el mantenimiento físico y el uso de la base de datos; ya sean uniones, replicación, múltiples fuentes de hardware para datos u otros.
Dado que la única razón para la introducción de una clave sustituta es el rendimiento, supongamos que deseamos que sea eficaz. Si el problema de rendimiento en cuestión son las uniones, entonces necesariamente deseamos que nuestra clave sustituta sea lo más estrecha posible (sin interferir en el hardware, por lo que generalmente se eliminan los enteros cortos y los bytes). El rendimiento de la unión depende de una altura de índice mínima, por lo que un entero de 4 bytes es una solución natural. Si su problema de rendimiento es la tasa de inserción, un entero de 4 bytes también puede ser una solución natural (dependiendo de las partes internas de su RDBMS). Si su problema de rendimiento para una tabla es la replicación o múltiples fuentes de datos que alguna otra tecnología de clave sustituta , ya sea un GUID o una clave de dos partes (Host ID + entero) puede ser más adecuado. No soy personalmente un favorito de los GUID, pero son convenientes.
En resumen, no todas las tablas requerirán una clave sustituta (de ningún tipo); solo deben usarse cuando se considere necesario para el desempeño de la tabla en consideración. Independientemente de la tecnología de clave sustituta común que prefiera, piense detenidamente sobre las necesidades reales de la tabla antes de elegir; Cambiar la opción de tecnología clave sustituta para una mesa será un trabajo agotador. Documente la métrica clave de rendimiento de su tabla para que sus sucesores comprendan las elecciones realizadas.
Casos especiales
Si los requisitos de su negocio exigen una numeración secuencial de transacciones para fines de auditoría (u otros) que ese campo no es una clave sustituta; Es una clave natural (con requisitos adicionales). De la documentación, un entero de incremento automático solo genera claves sustitutas , por lo tanto, busque otro mecanismo para generarlo. Obviamente, será necesario algún tipo de monitor, y si obtiene sus transacciones de varios sitios, entonces un sitio será especial , en virtud de ser el sitio host designado para el monitor.
Si su tabla nunca tendrá más de cien filas, la altura del índice es irrelevante; cada acceso se realizará mediante un escaneo de tabla. Sin embargo, las comparaciones de cadenas en cadenas largas seguirán siendo mucho más caras que la comparación de un entero de 4 bytes, y más caras que la comparación de un GUID.
Una tabla de valores de código tecleados por un campo de código char (4) debe tener el mismo rendimiento que uno con un entero de 4 bytes. Aunque no tengo pruebas de esto, uso el supuesto con frecuencia y nunca he tenido motivos para lamentarlo.
fuente
No solo no es una buena práctica, de hecho, se describe como un antipatrón en el libro SQL Antipatterns de Bill Karwin.
No todas las tablas necesitan una pseudoclave, una clave primaria con un valor arbitrario, no algo que tenga un valor semántico para el modelo, y no hay razón para llamarla siempre
id
.fuente
Esto es bastante universal; de lo contrario, deberá validar que la clave sea realmente única. Esto se haría mirando todas las otras claves ... lo que llevaría mucho tiempo. Tener una clave incremental se vuelve costoso a medida que su número de registro se acerca al valor de desbordamiento de la clave.
Por lo general, hago que los punteros sean nombres de campo más obvios, como
ref_{table}
idea similar o similar.Si no es necesario señalar externamente un registro, entonces no necesita una identificación.
fuente
unsigned int
para el tipo de campo; de lo contrario, el límite es la mitad de ese número.No diría que siempre se debe hacer. Tengo una tabla aquí sin una clave única, y no necesita una. Es un registro de auditoría. Nunca habrá una actualización, las consultas devolverán todos los cambios a lo que se está registrando, pero eso es lo mejor que se puede hacer razonablemente, se necesita un humano para definir un cambio erróneo. (¡Si el código pudiera, lo habría rechazado en primer lugar!)
fuente
Un contador de incremento automático para una clave primaria no es una buena idea. Esto se debe a que debe volver a la base de datos para encontrar la siguiente clave e incrementarla en una antes de insertar sus datos.
Dicho esto, generalmente usaría lo que la base de datos pueda proporcionar para la clave primaria en lugar de tenerla como parte de la aplicación.
Al permitir que la base de datos se la proporcione de forma nativa, puede garantizar que la clave sea única para lo que necesita.
Por supuesto, no todas las bases de datos lo admiten. En cuyo caso, generalmente uso una tabla que almacena depósitos de claves y uso rangos altos y bajos que se administran en la aplicación. Esta es la solución más eficaz que encuentro porque obtienes un rango de 10000 números y los autoincrementas en la instancia de la aplicación. Otra instancia de aplicación puede recoger otro grupo de números para trabajar. Necesita una primitiva de clave primaria suficientemente grande, como una longitud de 64 bits.
UUID que no uso como claves primarias porque el costo de construirlos y almacenarlos es mucho mayor que incrementar un valor largo en uno. Los UUID todavía se ocupan de la paradoja del cumpleaños en que teóricamente puede surgir un duplicado.
fuente