En una discusión bastante animada en mi equipo, me hicieron pensar en lo que a la mayoría de la gente le gusta como claves primarias. Tuvimos los siguientes grupos-
- Int / BigInt cuyos aumentos automáticos son claves primarias suficientemente buenas.
- Debe haber al menos 3 columnas que componen la clave principal.
- Id, GUID y los identificadores de fila legibles por humanos deben tratarse de manera diferente.
¿Cuál es el mejor enfoque para los PK? Sería fantástico si pudiera justificar su opinión. ¿Existe un enfoque mejor que el anterior?
EDITAR: ¿Alguien tiene una muestra / algoritmo simple para generar identificadores legibles por humanos para filas que se escalan bien?
algorithm
database-design
relational-database
primary-key
ddl
Perpetualcoder
fuente
fuente
PK(NEWID(),NEWID(),NEWID())
;-)Respuestas:
Si va a realizar alguna sincronización entre bases de datos con aplicaciones conectadas ocasionalmente, entonces debería usar GUID para sus claves principales. Es una especie de molestia para la depuración, así que, aparte de ese caso, tiendo a ceñirme a los ints que autoincremento.
Los ints de autoincremento deben ser los predeterminados y no se debe justificar su uso.
fuente
CHAR(1)
hubiera sido suficiente, como parasex
. No hace falta decir que trabajar con él fue una pesadilla.No veo una respuesta que señale (lo que considero) el punto realmente fundamental, es decir, que una clave primaria es lo que garantiza que no obtendrá dos entradas en la tabla para la misma entidad del mundo real (como modelado en la base de datos). Esta observación ayuda a establecer qué opciones son buenas y malas para la clave primaria.
Por ejemplo, en una tabla de códigos y nombres de estados (EE. UU.), El nombre o el código podría ser la clave principal; constituyen dos claves candidatas diferentes, y una de ellas (normalmente la más corta, el código) se elige Clave primaria. En la teoría de las dependencias funcionales (y las dependencias de unión - 1NF a 5NF - son las claves candidatas las que son cruciales en lugar de una clave primaria.
Como contraejemplo, los nombres humanos generalmente son una mala elección para la clave primaria. Hay muchas personas que se conocen con el nombre de "John Smith" o algunos otros nombres similares; incluso teniendo en cuenta los segundos nombres (recuerde: no todo el mundo tiene uno, por ejemplo, yo no), hay muchas posibilidades de duplicación. En consecuencia, la gente no usa nombres como claves primarias. Inventan claves artificiales como el número de seguro social (SSN) o el número de empleado y las utilizan para designar a la persona.
Una clave primaria ideal es breve, única, memorable y natural. De estas características, la singularidad es obligatoria; el resto tiene que ser flexible dadas las limitaciones de los datos del mundo real.
Cuando se trata de determinar la clave principal de una tabla dada, por lo tanto, debe observar lo que representa esa tabla. ¿Qué conjunto o conjuntos de valores de columna de la tabla identifican de forma única cada fila de la tabla? Esas son las claves candidatas. Ahora, si cada clave candidata consta de 4 o 5 columnas, entonces puede decidir que son demasiado torpes para hacer una buena clave primaria (principalmente por razones de brevedad). En esas circunstancias, puede introducir una clave sustituta, un número generado artificialmente. Muy a menudo (pero no siempre) un simple entero de 32 bits es suficiente para la clave sustituta. Luego, designa esta clave sustituta como clave principal.
Sin embargo, aún debe asegurarse de que las otras claves candidatas (porque la clave sustituta también es una clave candidata, así como la clave primaria elegida) se mantengan como un identificador único, normalmente colocando una restricción única en esos conjuntos de columnas.
A veces, a las personas les resulta difícil identificar qué es lo que hace que una fila sea única, pero debería haber algo para hacer eso, porque la simple repetición de una información no la hace más verdadera. Y si no tiene cuidado y obtiene dos (o más) filas que pretenden almacenar la misma información, y luego necesita actualizar la información, existe el peligro (especialmente si usa cursores) de que actualice solo una fila en lugar de cada fila, por lo que las filas no están sincronizadas y nadie sabe qué fila contiene la información correcta.
Esta es una opinión bastante dura, en algunos aspectos.
No tengo ningún problema en particular con el uso de un GUID cuando se necesitan, pero tienden a ser grandes (como en 16-64 bytes) y se usan con demasiada frecuencia. Muy a menudo, bastaría con un valor de 4 bytes perfectamente correcto. El uso de un GUID donde un valor de 4 bytes sería suficiente desperdicia espacio en disco y ralentiza incluso el acceso indexado a los datos, ya que hay menos valores por página de índice, por lo que el índice será más profundo y se deben leer más páginas para llegar al información.
fuente
Este es solo un problema religioso porque la gente busca una respuesta correcta universal. El hecho de que tanto su equipo como este hilo de SO muestren tanto desacuerdo debería ser una pista de que existen buenas razones para utilizar todas las soluciones que describe, en diferentes circunstancias.
state
(CA, TX, NY), también podría usar unachar(2)
clave natural en lugar de una int.id
clave sustituta " " innecesariamente cuando existe una clave compuesta perfectamente buena (esto es especialmente cierto en tablas de muchos a muchos). Un mandato para una clave de tres columnas en cada tabla es una absoluta tontería.fuente
Me gusta el blog The Database Programmer como fuente para este tipo de información.
3 columnas para una clave primaria? Yo diría que las columnas deberían tener restricciones únicas apropiadas según lo exijan las reglas de negocio, pero aún tendría una clave sustituta separada. Las claves compuestas significan que la lógica empresarial entra en la clave. Si la lógica cambia, todo tu esquema se arruina.
fuente
Me gusta la mía única.
fuente
Un poco fuera de tema, pero me siento obligado a intervenir con ...
Si su clave principal es un GUID, no lo convierta en un índice agrupado . Dado que los GUID no son secuenciales, los datos se reorganizarán en el disco durante casi todas las inserciones. (¡Qué asco!) Si usa GUID como claves primarias, deberían ser índices no agrupados.
fuente
Siempre voy con la llave sustituta. Una clave sustituta (generalmente una columna de identidad, autoincremento o GUID) es aquella en la que la clave no está presente en los datos en sí. Una clave natural, por otro lado, es aquella que, por sí sola, identifica de forma única la fila. Por lo que puedo decir en la vida, casi no hay claves naturales reales . Ni siquiera cosas como SSN en los Estados Unidos es una clave natural. Las claves primarias compuestas son un desastre a la espera de suceder. No puede editar ninguno de esos datos (que es el mayor inconveniente de cualquier clave natural, compuesta o no), pero lo peor es que con una clave compuesta, ahora tiene que perpetuar esos datos clave en cada tabla relacionada. Qué desperdicio gigante.
Ahora, para la selección de la clave sustituta, me quedo con las columnas de identidad (trabajo principalmente en MS SQL Server). Los GUID son demasiado grandes y Microsoft recomienda no usarlos como PK. Si tiene varios servidores, todo lo que necesita hacer es hacer el incremento de 10 o 20 o lo que crea que es el número máximo de servidores que necesitará sincronizar / expandir, y solo aumentar la semilla para cada tabla en cada servidor subsiguiente y nunca tendrá una colisión de datos.
Por supuesto, debido al incremento, hago que la columna de identidad sea un BigInt (también conocido como long [64 bits]).
Haciendo un poco de matemáticas, incluso si hace el incremento de 100, todavía puede tener 92,233,720,368,547,758 (> 92 cuatrillones) filas en su tabla.
fuente
Creo que el uso de la palabra "Primaria" en la frase Clave "Primaria" es, en un sentido real, engañoso.
Primero, use la definición de que una "clave" es un atributo o conjunto de atributos que deben ser únicos dentro de la tabla,
Entonces, tener cualquier clave sirve para varios propósitos que a menudo son incompatibles entre sí.
Para aumentar el rendimiento de las consultas que necesitan ubicar rápidamente un registro / fila específico en la tabla.
Para garantizar la coherencia de los datos evitando que se inserten en la tabla filas duplicadas que representan la misma entidad lógica. (Esto a menudo se denomina clave "natural" y debe constar de atributos de tabla (entidad) que son relativamente invariantes).
Claramente, cualquier clave no significativa, no natural (como un GUID o un entero generado automáticamente es totalmente incapaz de satisfacer # 4.
Pero a menudo, con muchas (la mayoría) de las tablas, una clave totalmente natural que puede proporcionar el n. ° 4 a menudo constará de múltiples atributos y será excesivamente amplia, o tan amplia que usarla para los propósitos n. ° 1, n. ° 2 o n. ° 3 causará inaceptables Consecuencias de rendimiento c.
La respuesta es simple. Utilice ambos. Use una clave integral de generación automática simple para todas las combinaciones y FK en otras tablas secundarias, pero asegúrese de que cada tabla que requiera consistencia de datos (muy pocas tablas no lo hagan) tenga una clave única natural alternativa que evitará inserciones de filas de datos inconsistentes. .. Además, si siempre tiene ambos, entonces todas las objeciones contra el uso de una clave natural (¿y si cambia? Tengo que cambiar cada lugar al que se hace referencia como FK) se vuelven discutibles, ya que no la está usando para eso. .. Solo lo está usando en la única tabla donde es un PK, para evitar datos duplicados inconsistentes ...
En cuanto a los GUID, tenga mucho cuidado al usarlos, ya que el uso de guids en un índice puede dañar la fragmentación del índice. Los algoritmos más comunes que se utilizan para crearlos colocan la parte "aleatoria" del guid en las posiciones de bits más significativas ... Esto aumenta el requisito de desfragmentación / reindexación de índice regular a medida que se agregan nuevas filas.
fuente
Una cosa que nunca debe hacer es usar una llave inteligente. Esa es una clave donde la información sobre el registro se codifica en la clave misma, y eventualmente lo morderá.
Trabajé en un lugar, donde la clave principal era el ID de cuenta, que era una combinación de letras y números. No recuerdo ningún dato específico, pero, por ejemplo, aquellas cuentas que eran de cierto tipo, estarían en el rango de 600, y de otro tipo, comenzaban con 400. Eso fue genial, hasta que ese cliente decidió pedir tanto tipos de trabajo. O cambiaron el tipo de trabajo que hacían.
En otro lugar, se utilizó la ubicación en el árbol como clave principal para los registros. Entonces habría registros como el siguiente.
Por supuesto, lo primero que querían los clientes era una forma de mover los elementos del árbol. Todo el conjunto de software murió antes de que eso sucediera.
Por favor, por favor, por favor, si está escribiendo un código que alguna vez tengo que mantener, ¡no use una llave inteligente!
fuente
Soy fanático del incremento automático como clave principal. Sé en el fondo de mi corazón que esto es una evasión, pero hace que sea muy fácil ordenar los datos según el momento en que se agregaron (ORDER BY ID DESC, primera instancia).
3 columnas suena terriblemente duro de analizar humanamente.
Y esa es la compensación: cuánta capacidad relacional necesita, versus hacer que ESTA TABLA AQUÍ sea comprensible para un humano que la interroga (versus el procedimiento almacenado o la interfaz programática).
el auto incremento es para nosotros los humanos. :-(
fuente
Generalmente depende.
Personalmente, me gustan los ints de autoincremento.
Pero, una cosa que puedo decirle es que nunca confíe en los datos de otras fuentes como clave. Lo juro, cada vez que lo he hecho vuelve a morderme. Bueno, ¡nunca más!
fuente
No entiendo esto.
¿Estás hablando de una "clave natural", por ejemplo, "nombre y fecha de nacimiento"? Una clave natural puede ser ideal si existe, pero la mayoría de los candidatos para una clave natural no son únicos (varias personas con el mismo nombre) o no son constantes (alguien puede cambiar su nombre).
Prefiero a Guid. Un problema potencial con el autoincremento es que el valor (por ejemplo, "ID de pedido") es asignado por la instancia de la base de datos (por ejemplo, por la "base de datos de ventas") ... que no funcionará por completo (en su lugar, empezará a necesitar claves compuestas) si siempre necesita fusionar datos creados por más de una instancia de base de datos (por ejemplo, de varias oficinas de ventas, cada una con su propia base de datos).
fuente
RE GUID's
Tenga cuidado si esto va a ser una base de datos realmente, REALMENTE REALMENTE grande, mucha carga y acceso rápido.
En mi último trabajo, donde teníamos bases de datos de 100 a 500 millones de registros, nuestros chicos de bases de datos se opusieron firmemente a los GUID y a favor de un número decimal del tamaño adecuado. Consideraron que (bajo Oracle) la diferencia de tamaño en el almacenamiento interno para una cadena Guid - vs- un valor decimal haría una diferencia muy notable en las búsquedas. (Teclas más grandes = árboles más profundos para atravesar)
La naturaleza aleatoria de los GUID también reduce significativamente el factor de relleno de las páginas de índice, lo que aumenta drásticamente el desgarro y la E / S del disco.
fuente
Columnas de incremento automático. Puedo hacer que mi código funcione sin problemas con SQL Server u Oracle, uno usando identidad y el otro usando secuencias a través de mi DAL, y no podría estar más feliz. Estoy de acuerdo, los GUID a veces son necesarios si está realizando una replicación o enviando datos para recibirlos más tarde después del procesamiento.
fuente
Siempre he usado una clave sustituta, un número entero que aumenta automáticamente y se llama 'id'. Puedo ver muchas razones para hacer esto incluso cuando otra opción es obvia:
... y no hay ninguna razón sensata para no:
razones sensatas en contra de las que no he pensado o encontrado todavía son siempre bienvenidas ...
fuente
Este es un clásico "depende". No hay una respuesta correcta para cada proyecto. Me gustan cosas diferentes para situaciones diferentes. Depende de si estoy usando un ORM y de lo que admite. Depende de la arquitectura general (distribuida o no, etc.). Simplemente elija uno que crea que funcionará y continúe discutiendo sobre tabulaciones y espacios.
fuente
Tiendo a usar la opción # 1 o # 3 dependiendo del tamaño, la cantidad de personas que se conectan y si se trata de una situación de servidor de base de datos múltiple o no.
La opción # 2 no tiene mucho sentido para mí. Si alguno de los tres no es suficiente para identificar un registro único, entonces es posible (sin pasar por maquinaciones adicionales) que dos tengan dos registros que aparezcan con los mismos valores en las tres columnas. Si desea hacer cumplir la singularidad en cualquier combinación de los tres, simplemente agregue un índice para ellos.
fuente
Solo he usado un int de incremento automático o un GUID. El 99% de las veces utilizo el incremento automático int. Es solo lo que me enseñaron a usar cuando aprendí por primera vez sobre bases de datos y nunca me he encontrado con una razón para no usarlas (aunque conozco las razones por las que un GUID sería mejor).
Me gustan los ints de incremento automático porque ayuda con la legibilidad. Por ejemplo, puedo decir "eche un vistazo al registro 129383" y es bastante fácil para alguien entrar y encontrarlo. Con un GUID eso es casi imposible de hacer.
fuente
Más allá de una respuesta de definición básica, lo que constituye una buena clave primaria se deja en gran parte a la religión y los argumentos de la sala de descanso. Si tiene algo que es, y siempre, se asignará de forma única a una fila individual, entonces funcionará bien como clave principal. Más allá de ese punto, hay otras consideraciones:
Este último es probablemente lo que atrae a la mayoría de las personas a usar cosas como GUID o columnas de números enteros que se incrementan automáticamente, porque confiar en cosas como direcciones, números de teléfono, nombres / apellidos, etc., simplemente no lo corte. La única invariante sobre las personas en las que puedo pensar son los números de seguro social, pero ni siquiera estoy 100% seguro de que esos sigan siendo únicos para siempre.
Con suerte, esto ayuda a agregar algo de claridad ...
fuente
La forma en que me acerco a las claves primarias (y creo que es la mejor) es evitar tener un enfoque "predeterminado". Esto significa que en lugar de simplemente dar una palmada a un entero que se incrementa automáticamente y llamarlo un día, miro el problema y digo "¿hay una columna o grupo de columnas que siempre será unqiue y no cambiará?" Si la respuesta es sí, entonces adopto ese enfoque.
fuente
Casi siempre enteros.
Tienen otras buenas razones además de ser más pequeñas / más rápidas de procesar. ¿Cuál preferiría escribir: "404040" o "3463b5a2-a02b-4fd4-aa0f-1d3c0450026c"?
fuente
Solo un poco relevante, pero una cosa que comencé a hacer recientemente cuando tengo pequeñas tablas de clasificación (esencialmente aquellas que representan ENUM en el código) es que haré que la clave principal sea char (3) o char (4). Luego hago que esas claves primarias sean representativas del valor de búsqueda.
Por ejemplo, tengo un sistema de cotización para nuestros agentes de ventas internos. Tenemos "Categorías de costos" a las que a cada artículo de línea de cotización se le asigna una de ... Así que tengo una tabla de búsqueda de tipos llamada 'tCostCategories', donde la clave principal es 'MTL', 'SVC', 'TRV', 'TAX', 'ODC'. Otras columnas en la tabla de búsqueda almacenan más detalles, como los significados en inglés normales de los códigos, "Material", "Servicio", "Viajes", "Impuestos", "Otros costos directos", etc.
Esto es realmente bueno porque no usa más espacio que un int, y cuando está mirando los datos de origen, no tiene que vincular la tabla de búsqueda para saber cuál es el valor. Por ejemplo, una fila de cotización podría verse así:
1 Número de pieza $ 40 MTL
2 Otro Número de pieza $ 29.99 SVC
3 Número de pieza 2 $ 150 TRV
Es mucho más fácil que usar un int para representar las categorías y luego vincular 1, 2, 3 en todas las líneas: tiene los datos justo frente a usted y el rendimiento no parece afectado en absoluto (no es que yo ' realmente he probado.)
En cuanto a la verdadera pregunta ... me gustan los identificadores únicos RowGUID. No estoy al 100% en esto, pero ¿no todas las filas tienen RowGuid internos de todos modos? Si es así, usar RowGuid en realidad tomaría menos espacio que los ints (o cualquier otra cosa). Todo lo que sé es que si es lo suficientemente bueno para que M $ lo use en GreatPlains, entonces es lo suficientemente bueno para mí. (¿Debería agacharme?)
fuente
Oh, una razón más por la que uso GUID: uso una estructura de datos jerárquica. Es decir, tengo una tabla 'Compañía' y una tabla 'Proveedor' para las que coinciden las claves primarias. Pero también tengo una tabla 'Fabricante' que también 'hereda' de la Compañía. Los campos que son comunes a proveedores y fabricantes no aparecen en esas tablas, aparecen en Compañía. En esta configuración, el uso de int es mucho más doloroso que Guids. Como mínimo, no puede usar claves primarias de identidad.
fuente
Me gustan las claves naturales, siempre que puedo confiar en ellas. Estoy dispuesto a pagar un pequeño precio por rendimiento para utilizar claves que tengan sentido para los expertos en la materia.
Para las tablas que describen entidades, debe haber una clave natural simple que identifique instancias individuales de la misma manera que lo hacen las personas de la materia. Si el tema no tiene identificadores confiables para una de las entidades, entonces recurriré a una clave sustituta.
Para las tablas que describen relaciones, utilizo una clave compuesta, donde cada componente hace referencia a una entidad que participa en la relación y, por lo tanto, a una fila en una tabla de entidad. Nuevamente, el impacto en el rendimiento por usar una clave compuesta es generalmente mínimo.
Como han señalado otros, el término "clave primaria" es un poco engañoso. En el modelo de datos relacionales, el término que se utiliza es "claves candidatas". Podría haber varias claves candidatas para una sola tabla. Lógicamente, cada uno es tan bueno como el otro. Elegir uno de ellos como "principal" y hacer todas las referencias a través de esa clave es simplemente una elección que el diseñador puede hacer.
fuente
Guids.period.
En el caso de que necesite escalar horizontalmente o necesite asignar la clave principal por medios alternativos, serán sus amigos. Puede agregar índices para todo lo demás.
actualizar para aclarar mi declaración.
He trabajado en muchos tipos diferentes de sitios. Desde pequeños acuerdos de un solo servidor hasta grandes respaldados con múltiples bases de datos y servidores web. Ciertamente, ha habido aplicaciones que hubieran estado bien con el incremento automático de ints como claves primarias. Sin embargo, esos no se ajustan al modelo de cómo hago las cosas.
Cuando usa un GUID, puede generar el ID en cualquier lugar. Puede ser generado por un servidor remoto, su aplicación web, dentro de la propia base de datos o incluso dentro de varias bases de datos en una situación de varios maestros.
Por otro lado, un INT autoincrementado solo se puede generar de forma segura dentro de la base de datos primaria. Nuevamente, esto podría estar bien si tiene una aplicación que estará íntimamente ligada a ese servidor de base de datos de respaldo y el escalado horizontal no es algo que le preocupe.
Claro, el uso de GUID significa que debe tener procesos de reindexación nocturnos. Sin embargo, si está utilizando algo que no sea un INT incrementado automáticamente, debe hacerlo de todos modos. Diablos, incluso con un INT como principal, es probable que tenga otros índices que necesiten regenerarse para lidiar con la fragmentación. Por lo tanto, el uso de GUID no agrega exactamente otro problema porque esas tareas deben realizarse independientemente.
Si echas un vistazo a las aplicaciones más grandes, notarás algo importante: todas usan GUID codificadas en Base64 como claves. La razón de esto es simple, el uso de GUID le permite escalar horizontalmente fácilmente, mientras que puede haber muchos obstáculos que superar al intentar escalar INT.
Nuestra última aplicación pasa por un período de inserciones pesadas que dura aproximadamente un mes. Después de eso, más del 90% de las consultas se seleccionan para informar. Para aumentar la capacidad, puedo activar servidores de base de datos adicionales durante este gran período de inserción; y luego fusionarlos fácilmente en una sola base de datos para generar informes. Intentar hacer eso con INT sería una pesadilla absoluta.
Francamente, cada vez que agrupa una base de datos o configura la replicación, el servidor de base de datos exigirá que tenga GUID en la mesa de todos modos. Por lo tanto, si cree que su sistema podría necesitar crecer, elija el que sea bueno.
fuente
Este es un tema complejo, te hayas dado cuenta o no. Podría incluirse en la sección de estas preguntas frecuentes de StackOverflow.
¿Qué tipo de preguntas no debería hacer aquí?
Evite hacer preguntas subjetivas, argumentativas o que requieran una discusión extensa. ¡Este es un lugar para preguntas que pueden responderse!
Esto se ha debatido durante años y seguirá debatiéndose durante años. Los únicos indicios de consenso que he visto es que las respuestas son algo predecibles dependiendo de si le estás preguntando a un tipo de OO (¡los GUID son el único camino a seguir!), Un modelador de datos (¡las claves naturales son el único camino a seguir!), o un DBA orientado al rendimiento (¡los INT son el único camino a seguir!).
fuente