¿Estas tablas específicas necesitan claves sustitutas?

13

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.

ingrese la descripción de la imagen aquí

country_code es el código de país estándar ISO 3166-1 A3 , puede verlos en los Juegos Olímpicos.

ingrese la descripción de la imagen aquí

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.

ingrese la descripción de la imagen aquí

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é?

Tulains Córdova
fuente

Respuestas:

15

No, no lo hacen. ¡Esas llaves son definitivamente lo suficientemente buenas!

Son únicos, no rara vez van a cambiar y son significativos , lo que es un paso adelante en una clave sustituta. Esa es más o menos la definición de una buena PK.

Las restricciones sobre PK son inmutables y enteros numéricos no son parte del Modelo Relacional (Codd's) ni de ningún estándar SQL (ANSI u otro).

Bobson
fuente
3
Las claves primarias también deben ser inmutables, algo que los códigos de aeropuerto IATA definitivamente no lo son. Se pueden cambiar a voluntad de la IATA.
James Snell
3
@JamesSnell: los códigos de aeropuerto IATA son casi tan inmutables como los códigos de país. Estás hablando de un cambio tal vez una vez cada década, si eso es así. Vea aquí para una discusión del asunto. Hay muchos códigos obsoletos que todavía están en su lugar porque son demasiados problemas para cambiar. Además, para eso está la actualización CASCADE. Las claves primarias mutables son legítimas, si no una gran práctica.
Bobson
2
@EricKing Estos terceros están compuestos por representantes de los principales partidos de muchas industrias, luego se discuten los estándares durante años y luego se votan hasta que se alcanza un consenso razonable. También acuerdan los mecanismos a través de los cuales se realiza cualquier cambio o nueva adición. Además de eso, los estándares de listas de códigos se crean, no por capricho, sino porque existe la necesidad de crear una lista de códigos controlada, respetada y acordada para algo, con el fin de poder interoperar en todo el mundo y comunicarse adecuadamente en todo el mundo.
Tulains Córdova
2
@ user61852: se podría decir que estos estándares están hechos para ser claves principales.
Bobson
3
@Bobson: "Hay muchos códigos obsoletos que todavía están en su lugar porque son demasiados problemas para cambiar" -> ¿posiblemente porque son claves principales?
Maciej
2

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í:

+-------------------------+  +------------------------+
|Airport                  |  |Country                 |
|-------------------------|  |------------------------|
|airport_id       int (PK)|  |country_id     int (PK) |
|iata_airport_code string |  |iso_country_code string |
|icao_airport_code string |  +------------------------+
|faa_identifier    string |  
|address           string |  
|name              string |  
+-------------------------+

+-------------------------+
|Currency                 |
|-------------------------|
|currency_id int (PK)     |
|iso_currency_code string |
|name string              |
+-------------------------+

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 :

La mayoría de los países utilizan códigos ICAO de cuatro caracteres , no códigos IATA, en sus publicaciones aeronáuticas oficiales.

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.

Eric King
fuente
1
¿Entonces los estándares IATA son lo suficientemente buenos para las aerolíneas pero no para usted?
Tulains Córdova
1
Por supuesto, tendrá que unirse hasta la mesa del aeropuerto cuando desee buscar equipaje en el Heathrow de Londres, porque no puede hacerlo 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.
Tulains Córdova
1
Los códigos IATA no son inmutables, por lo tanto, no pueden considerarse candidatos PK. Ejemplo: el código IDL estaba en Nueva York, hasta que pasó a llamarse JFK. El código IDL ahora está en Mississippi.
James Snell
2
@EricKing IATA e ISO se preocupan de que los códigos sean lo suficientemente estables, únicos y aceptados universalmente. Eso coincide mucho con el interés de una persona que diseña una mesa.
Tulains Córdova
2
@ user61852: el hecho de que estos sean códigos estándar no significa que el sistema de la aerolínea los use como PK (¿quizás tenga más información aquí?). Tener una actualización en cascada a una escala tan masiva parece una muy mala idea.
JeffO
1

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ó:

Las claves primarias también deben ser inmutables, algo que los códigos de aeropuerto IATA definitivamente no lo son. Se pueden cambiar a voluntad de la IATA.

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?

Toni Kostelac
fuente
Es un pensamiento válido, pero el objetivo de estas tablas es que solo hay una cantidad finita de registros en cada tabla. Si realmente quiso decir el tamaño del código con small projecty bigger, actualice para aclarar por qué eso sería importante.
Bobson
1
Las restricciones sobre PK son inmutables y enteros numéricos no son parte del Modelo Relacional (Codd's) ni de ningún estándar SQL (ANSI u otro).
Tulains Córdova
44
Los índices basados ​​en cadenas cortas de longitud fija (como los códigos ISO) son tan rápidos como los enteros. Índices basados ​​en longitud variable, las cadenas largas no lo son.
Tulains Córdova
Eso es lo que dije (vea la parte VARCHAR vs CHAR arriba) No he tenido la oportunidad de probar una cadena corta de longitud fija frente a un entero numérico, pero tuve la oportunidad de hacerlo con una longitud variable y un entero
Toni Kostelac
2
Unirse a la actuación es un hombre de paja. A menudo, el uso de claves naturales significa que no necesita una unión en primer lugar.
Mike Sherrill 'Cat Recall'
1

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.

JeffO
fuente
+1 Gran respuesta. La mayoría de las veces la gente es muy dogmática sobre este tema. Muchos diseñadores de bases de datos tienen un ego gigante y se consideran dueños de la base de datos y los datos. Otros ven bien que el propietario de los datos solo puede usarlos a través de una aplicación específica, porque no puede entenderlos. También prefieren hacer provisiones para algo que puede suceder o no en el futuro mientras hacen un montón de cosas que se hacen a diario, como importar datos y escribir consultas. Tampoco se produce ningún tipo de bibliografía canónica que respalde su punto de vista.
Tulains Córdova
Por cierto, la regla "Yo uso claves sustitutas todo el tiempo" no está en el Modelo Relacional (Codd's) ni en ningún estándar SQL. El esquema del diccionario de datos de Oracle utiliza claves naturales siempre que sea posible y claves artificiales en los demás casos. PPDM ( ppdm.org ) también recomienda el enfoque mixto y lo usa en su modelo. ANSI SQL Standard no dice nada acerca de todos los sustitutos. Creo que todos los sustitutos y todos los naturales son corrosivos. Algunos modelos naturales y otros sustitutos es lo que enseñan los modelos relacionales.
Tulains Córdova