Antecedentes
Tengo estas tablas
+-------------------------+ +------------------------+
|Airport | |Country |
|-------------------------| |------------------------|
|airport_code string (PK) | |country_code string (PK)|
|address string | |name string |
|name string | +------------------------+
+-------------------------+
+-------------------------+
|Currency |
|-------------------------|
|currency_code string (PK)|
|name string |
+-------------------------+
airport_code es el código de aeropuerto IATA (International Air Transport Association) , puede verlos en sus etiquetas de equipaje cuando viaja en avión.
country_code es el código de país estándar ISO 3166-1 A3 , puede verlos en los Juegos Olímpicos.
currency_code es el código de moneda estándar de 3 caracteres IS0 417 , puede verlos en las pantallas de cambio de moneda internacional.
Preguntas
¿Son estas PK naturales lo suficientemente buenas?
¿El uso de estándares respetados en el mundo, que son aceptados por industrias enteras, es lo suficientemente bueno para las PK?
¿Estas tablas necesitan sustitutos sin importar qué?
fuente
Creo que necesidad es una palabra muy fuerte, y en un sentido estricto, las tablas probablemente no necesitan claves sustitutas .
Sin embargo, si fuera mi base de datos, probablemente agregaría claves sustitutas de todos modos. Es posible que no necesariamente quiera que el diseño de mi base de datos dependa de un grupo de terceros (IATA, ISO), independientemente de cuán estables sean sus estándares. O bien, es posible que no quiera depender de un estándar en particular (¿hay otros estándares de código de moneda? No lo sé). Probablemente modelaría mis tablas con claves sustitutas así:
En otras palabras, a menos que esos códigos estándar de la industria sean inherentemente importantes para mi aplicación, no los usaría como PK de mis tablas. Son solo etiquetas. La mayoría de mis otras tablas probablemente tendrán claves sustitutas de todos modos, y esta configuración agregaría consistencia a mi modelo de datos. El costo de 'agregar' las claves sustitutas es mínimo.
Actualización basada en algunos de los comentarios:
Sin conocer el contexto de las tablas de ejemplo, es imposible saber qué tan importantes son los códigos de aeropuerto IATA para la aplicación que utiliza la base de datos. Obviamente, si los códigos IATA son centralmente importantes y se usan de manera generalizada en toda la aplicación, podría ser la decisión correcta, después de un análisis adecuado, usar los códigos como PK de la tabla.
Sin embargo, si la tabla es solo una tabla de búsqueda que se utiliza en algunos rincones de la aplicación, la importancia relativa de los códigos IATA puede no justificar un lugar tan destacado en la infraestructura de la base de datos. Claro, es posible que tenga que hacer una unión adicional en algunas consultas aquí y allá, pero ese esfuerzo puede ser trivial en comparación con el esfuerzo que tomaría hacer la investigación para asegurarse de que comprende completamente las implicaciones de hacer que los códigos IATA campo de clave primaria. En algunos casos, no solo no me importa, sino que no quiero tener que preocuparme por los códigos IATA. El comentario de @James Snell a continuación es un ejemplo perfecto de algo de lo que podría no tener que preocuparme para afectar el PK de mis tablas.
Además, la consistencia en el diseño es importante. Si tiene una base de datos con docenas de tablas que han diseñado consistentemente claves sustitutas, y luego algunas tablas de búsqueda que usan códigos de terceros como PK, eso introduce una inconsistencia. Eso no es del todo malo, pero requiere atención adicional en la documentación y tal cosa que no esté justificada. Son tablas de búsqueda por amor de Dios, simplemente usando una clave sustituta para la consistencia está perfectamente bien.
Actualización basada en investigaciones adicionales:
Ok, la curiosidad me mordió y decidí investigar un poco sobre los códigos del aeropuerto IATA por diversión, comenzando con los enlaces provistos en la pregunta.
Resulta que los códigos IATA no son tan universales y autorizados como la pregunta los hace ser. De acuerdo con esta página :
Además, los códigos IATA y los códigos ICAO son distintos de los códigos identificadores de la FAA , que son otra forma de identificar los aeródromos.
Mi objetivo al mencionar esto no es comenzar un debate sobre qué códigos son mejores o más universales o más autoritarios o más completos, sino mostrar exactamente por qué diseñar su estructura de base de datos en torno a un identificador arbitrario de terceros no es algo que elegiría hacer , a menos que haya una razón comercial específica para hacerlo .
En este caso, creo que mi base de datos estaría mejor estructurada, más estable y más flexible, al renunciar a los códigos IATA (o cualquier código de terceros potencialmente modificable) como candidato de clave principal y usar una clave sustituta. Al hacerlo, puedo renunciar a posibles dificultades que puedan surgir debido a la selección de clave principal.
fuente
select * from baggage where airport_code = 'LHR'
, lo que significa que la base de datos solo es utilizable para lanzar la aplicación, que es muy estrecha y patentada enfoque, especialmente cuando el dueño del negocio es el que pagó por la base de datos y, por lo tanto, la posee. También tendrá que escribir código para hacer cosas mundanas como importar datos de una base de datos a otra para evitar colisiones PK.Si bien tener claves sustitutas en los campos está bien y no hay nada de malo en que algo a tener en cuenta podría ser el tamaño de la página de índice en sí.
Dado que esta es una base de datos relacional, hará muchas uniones y tener una clave sustituta de tipo numérico podría facilitar el manejo de la base de datos, es decir, el tamaño de la página de índice será más pequeño y, por lo tanto, más rápido para buscar. Si este es un proyecto pequeño, no importará y pasará sin problemas, sin embargo, cuanto más grande sea la aplicación, más querrá reducir los cuellos de botella.
Tener un BIGINT, INT, SMALLINT, TINYINT o cualquier tipo de datos de tipo entero podría ahorrarle algunos problemas en el futuro.
Solo mis 2 centavos
ACTUALIZAR:
Pequeño proyecto: utilizado por unas pocas, tal vez incluso unas pocas docenas de personas. Pequeña escala, proyecto de demostración, proyecto para uso personal, algo para agregar a una cartera cuando presenta sus habilidades sin experiencia, y cosas por el estilo.
Proyecto grande: utilizado por miles, decenas de miles, millones de usuarios diariamente. Algo que construirías para una empresa nacional / internacional con una gran base de usuarios.
Por lo general, lo que sucede es que algunos de los registros seleccionados se seleccionan con frecuencia, y el servidor almacena en caché los resultados para un acceso rápido, pero de vez en cuando debe acceder a un registro menos utilizado, momento en el cual el servidor tendría que sumergirse en el índice página. (en el ejemplo anterior con los nombres de los aeropuertos, las personas a menudo vuelan aerolíneas nacionales, por ejemplo, Chichago -> Los Ángeles, pero con qué frecuencia vuelan desde Boston -> Zimbabwe)
Si se usa VARCHAR, eso significa que el espaciado no es uniforme, a menos que los datos sean siempre de la misma longitud (en ese momento, un valor CHAR es más efectivo). Esto hace que la búsqueda en el índice sea más lenta, y dado que el servidor ya está ocupado manejando miles y miles de consultas por segundo, ahora tiene que perder el tiempo yendo a través de un índice no uniforme y hacer lo mismo nuevamente en las uniones (que es más lento que selecciones regulares en una tabla no optimizada, tome DW como ejemplo donde haya la menor cantidad posible de uniones para acelerar la recuperación de datos). Además, si usa UTF que también puede interferir con el motor de la base de datos (he visto algunos casos).
Personalmente, desde mi propia experiencia, un índice correctamente organizado puede aumentar la velocidad de una unión en un ~ 70%, y hacer una unión en una columna entera puede acelerar la unión en aproximadamente un 25% (dependiendo de los datos) . A medida que las tablas principales comienzan a crecer y estas tablas se utilizan en ellas, preferiría que un tipo de datos entero ocupe la columna que tiene unos pocos bytes en lugar de tener un campo VARCHAR / CHAR que ocupará más espacio. Todo se reduce a ahorrar espacio en disco, aumentar el rendimiento y la estructura general de una base de datos relacional.
Además, como James Snell mencionó:
Entonces, teniendo esto en cuenta, ¿preferiría tener que actualizar 1 registro vinculado a un número, en lugar de tener que actualizar ese registro más todos los registros de la tabla en la que se une?
fuente
small project
ybigger
, actualice para aclarar por qué eso sería importante.Si adopta el enfoque "Uso claves sustitutivas todo el tiempo", puede evitar este tipo de preocupación. Puede que no sea algo bueno porque es importante pensar un poco en sus datos, pero sin duda ahorra mucho tiempo, energía y esfuerzo. Si alguien adoptara una aceptación de esta regla, los ejemplos enumerados ciertamente califican porque se necesita un "acto de congreso" cercano para realizar el cambio.
Las consultas ad hoc de una base de datos con estas claves naturales son ciertamente útiles. Crear vistas que hagan lo mismo al incluir las tablas de búsqueda puede funcionar igual de bien. Las bases de datos modernas hacen un trabajo mucho mejor con este tipo de cosas hasta el punto en que probablemente no importe.
Hay algunos casos específicos de los EE. UU., Donde los estándares se cambiaron drásticamente: el código postal se expandió de 5 a 9 dígitos, las abreviaturas estatales a 2 letras consistentes y se eliminó el período (¿Recuerdas cuando Illinois estaba enfermo?) Y la mayoría de el mundo tuvo que lidiar con Y2K. Si tiene una aplicación en tiempo real con datos repartidos por todo el mundo que contienen miles de millones de registros, las actualizaciones en cascada no son la mejor idea, pero ¿no deberíamos trabajar todos en lugares que enfrentan tales desafíos? Con ese conjunto de datos, puede probarlo usted mismo y llegar a una respuesta más difícil.
fuente