¿Cuáles son las ventajas y desventajas de incrementar los identificadores frente a las claves de texto completo para los diseños de claves externas?

8

En muchos diseños de bases de datos relacionales hay campos a los que se hace referencia en otras tablas.

Por ejemplo, considere una tabla de usuario con un nombre de usuario único y una segunda tabla que almacena datos de dirección.

Una disposición posible, que diría que es el enfoque común, porque he observado en la mayoría de los programas, es usar identificadores de incremento automático como este:

Table users
===========
userId int primary auto_increment
userName varchar unique

Table adressdata
==========
userId int references users.userId
adress_type varchar // for example country
address_value varchar // for example US
(you probably also want to put a unique key on (userId,adress_type))

Así es como solía hacerlo y cómo lo he visto en la mayoría de los casos.

Otra forma sería:

Table users
===========
userName varchar primary

Table adressdata
==========
userName varchar references users.userName
adress_type varchar // for example country
address_value varchar // for example US
(you probably also want to put a unique key on (userName,adress_type))

Aquí almacenamos el nombre de usuario completo también en la tabla de dirección de datos.

Para mí esto tiene las siguientes ventajas:

  • Puede seleccionar el nombre de usuario directamente desde la tabla sin la necesidad de unirlo a otra tabla. En este ejemplo, esto es desde el punto de vista de la aplicación, probablemente no tan relevante, pero es solo un ejemplo.

  • Puede ser más fácil escalar la base de datos en un entorno de replicación maestro-maestro, porque no hay conflictos de aumento automático.

Pero también las desventajas:

  • Los requisitos de espacio para el índice y los datos (pero probablemente más relevante será el índice) en el campo de la segunda tabla son más altos.
  • Un cambio del nombre de usuario necesitaría propagarse a todas las tablas, lo que consume más recursos que simplemente cambiarlo en una tabla y dejar los identificadores como están.

En mi opinión, es mucho más fácil trabajar con campos de texto y no usar identificadores de incremento, y las compensaciones son mínimas y en la mayoría de las aplicaciones no son relevantes.

Por supuesto, algunos objetos SE identifican con un número creciente por su naturaleza (por ejemplo, las publicaciones del foro deberían recibir una identificación creciente porque probablemente no haya otro campo único como el título más o menos).

Pero antes de comenzar a diseñar los diseños de mi base de datos de una manera completamente diferente, me gustaría saber si hay cosas en las que no pensé.

  • ¿Hay alguna mejor práctica?

  • ¿Hay pros / contras que no pensé y cuyo efecto puede surgir en un momento posterior en el tiempo?

  • ¿Cómo diseñas personalmente las bases de datos con respecto a los puntos anteriores y por qué?

Joe Hopfgartner
fuente

Respuestas:

3

Sugeriría usar la identificación y no el nombre de usuario, porque si comienza a usar el nombre de usuario como una columna de unión en varias tablas, debe recordar actualizarlas todas.

La clave foránea para la userstabla se convierte en la clave primaria de la addressdatatabla y la clave primaria debe permanecer estable. Es una buena práctica no cambiar los campos de clave principal. Debe existir una clave principal cuando se crea el registro, y debe permanecer sin cambios durante toda la vida útil del registro.

Si desea obtener más información El gran debate de la clave primaria es un gran artículo.

stivlo
fuente
2

Estoy fuertemente en el campo "no use llaves naturales". Eso es porque he visto lo difícil que es en el sistema cuando se actualizan y prácticamente todas las claves naturales que involucran nombres de cualquier tipo se actualizan.

Las bases de datos están optimizadas para usar combinaciones. Sí, puede guardar algunas combinaciones utilizando teclas naturales, pero el rendimiento se ve afectado cuando necesita actualizar 1,000,000 de registros porque un grupo de claves naturales cambiadas (o incluso dependiendo de lo que esté sucediendo) puede ser un gran obstáculo.

Solo usaría claves naturales bajo dos condiciones:

  1. si la clave está bastante garantizada para no cambiar (piense en los números VIN del automóvil) y
  2. si nunca se va a reutilizar (incluso cosas únicas como números de teléfono y correos electrónicos no son candidatos para un PK porque se reutilizan cuando alguien deja de usarlos).

Y, por supuesto, demasiadas claves naturales que se supone que son únicas no lo son. Si le preocupa la replicación, puede usar GUID.

HLGEM
fuente
1

El artículo de Wikipedia sobre la clave sustituta tiene algunas partes interesantes diseminadas:

  • "Los atributos que identifican de forma única una entidad podrían cambiar, lo que podría invalidar la idoneidad de las claves compuestas naturales " user name.
  • "Las claves sustitutas no cambian mientras exista la fila " . Por lo tanto, no es necesario (en forma manual o automática) cambiar las claves en cascada a las tablas de referencias.
  • " Los valores de las claves sustitutas generadas no tienen relación con el significado del mundo real de los datos almacenados en una fila " . Esto puede dificultar la auditoría.

Creo que el lector atento puede encontrar puntos adicionales a considerar.


fuente
Buena respuesta. Muchas claves naturales tienen tendencia a los cambios. Esto los hace inadecuados para claves que pueden ser referenciadas como claves foráneas. Hay muchas razones por las que es apropiado cambiar el ID de usuario de un usuario.
BillThor
1

Publicaré desde mi experiencia, que probablemente será muy diferente de lo que podrían sugerir varios DBA. Estoy orientado principalmente hacia la combinación de rendimiento y facilidad de mantenimiento al diseñar bases de datos para varios proyectos.

Yo nunca, nunca utilizar una clave natural para la clave principal. Especialmente si uso MySQL / InnoDB. Todavía no he visto ningún beneficio en el uso de una clave natural, por lo general, lo que veo son implicaciones de rendimiento, si es que nada. En negrita "nunca, nunca" solo porque las claves naturales solían crear cerdos de rendimiento para mis proyectos. El sustituto (entero) siempre fue una mejor opción. Puede que algunos no estén de acuerdo, pero vivimos en un mundo donde el rendimiento juega un papel importante en la teoría.

Cuando se trata de JOIN, no trato de evitarlos a toda costa, pero tiendo a optimizarlos. Intento abusar del índice agrupado de InnoDB (clave primaria) tanto como sea posible. Si las uniones se realizan a través de PK, entonces son extremadamente rápidas. También tiendo a evitar los FK donde no tienen sentido. Honestamente, no me importaría tanto la integridad de los datos cuando se trata de vincular usuarios y su información de dirección. Lo aplicaría al vincular facturas a artículos para los usuarios. El uso excesivo de FK es una exageración y una pesadilla para mantener después de hacer referencia a todo, pensando que es un gran diseño para mantener relaciones en todo el lugar. En algún momento, las cosas deben cambiar y cuando MySQL comienza a quejarse con el error 150 constantemente, solo quiere volver a casa.

También mencionó la replicación y evitar conflictos debido a la naturaleza de los aumentos automáticos. Tenía un proyecto donde teníamos una cantidad de bases de datos que almacenaban información de ventas de productos, la cantidad de bases de datos era variable. Todos los días las bases de datos se replicaban en una base de datos "maestra" que usábamos para ejecutar informes. La forma en que evité los enfrentamientos PK fue creando una clave primaria compuesta de una parte de auto_increment y otra parte INT que denotaba la ubicación de donde provenía el registro. De esa manera pude rastrear de dónde vinieron las cosas y no perdí nada (los productos tenían la misma ID, solo se cambió el identificador de ubicación).

nótese bien
fuente