¿Usar la dirección de correo electrónico como clave principal?

234

¿Es la dirección de correo electrónico un mal candidato para la primaria en comparación con los números de incremento automático?

Nuestra aplicación web necesita que la dirección de correo electrónico sea única en el sistema. Entonces, pensé en usar la dirección de correo electrónico como clave principal. Sin embargo, mi colega sugiere que la comparación de cadenas será más lenta que la comparación de enteros.

¿Es una razón válida para no usar el correo electrónico como clave principal?

Estamos utilizando PostgreSQL.

robert
fuente
55
¿Qué quieres decir con 'primario'? Si la dirección de correo electrónico debe ser única, entonces es una clave y requiere una restricción única. Si decide 'promover' que sea 'primario' es arbitrario, a menos que haya una razón práctica para hacerlo, por ejemplo, optimizar un sistema de bajo rendimiento.
día
77
Si desea que su base de datos imponga una dirección de correo electrónico única, cree una columna con un índice único, pero no la use como clave principal.
James Westgate el
104
@robert ¿Qué pasa si alguien quiere cambiar su dirección de correo electrónico? ¿Vas a cambiar todas las claves foráneas también?
systemmpuntoout
3
@onedaywhen: casi no hay diferencia, pero la clave principal se agrupará de forma predeterminada, mientras que un índice único no lo será. Todavía querrá definir la clave principal, que será la clave de búsqueda de registro único predeterminada, el índice único simplemente impone la unicidad de la columna sobre un índice normal
James Westgate
3
@James Westgate: FYI, no existe la agrupación automática en PostgreSQL. Una CLAVE PRIMARIA se implementa en el disco exactamente igual que un ÍNDICE ÚNICO donde todos los campos NO SON NULOS.
Matthew Wood

Respuestas:

283

La comparación de cadenas es más lenta que la comparación int. Sin embargo, esto no importa si simplemente recupera un usuario de la base de datos utilizando la dirección de correo electrónico. Importa si tiene consultas complejas con múltiples combinaciones.

Si almacena información sobre usuarios en varias tablas, las claves externas para la tabla de usuarios serán la dirección de correo electrónico. Eso significa que almacena la dirección de correo electrónico varias veces.

Sjoerd
fuente
11
@Sjoerd: El problema no es que la dirección de correo electrónico se almacene varias veces, aunque eso es definitivamente ineficiente, sino a quién le importa el espacio en el disco duro hoy. La mayoría de las empresas no tienen escala de google, donde esto sería importante. El problema es que la dirección de correo electrónico no se puede cambiar después, porque es una clave principal y se hace referencia como clave externa.
Stefan Steiger
@StefanSteiger ¿Quién dijo algo sobre el espacio en el disco duro? Todo lo que almacene ocupará espacio en la RAM.
Jonathan Allen
En caso de que alguien se pregunte, como lo hice, una clave GUID sería equivalente a una clave de correo electrónico, creo.
tofutim
178

También señalaré que el correo electrónico es una mala elección para hacer un campo único, hay personas e incluso pequeñas empresas que comparten una dirección de correo electrónico. Y al igual que los números de teléfono, los correos electrónicos pueden reutilizarse. [email protected] puede pertenecer fácilmente a John Smith un año y a Julia Smith dos años después.

Otro problema con los correos electrónicos es que cambian con frecuencia. Si se está uniendo a otras tablas con eso como la clave, también deberá actualizar las otras tablas, lo que puede ser un gran éxito cuando una empresa cliente completa cambia sus correos electrónicos (lo que he visto suceder).

HLGEM
fuente
47
+1 por mencionar el problema de actualización en cascada. Es por eso que los amigos dejan que los amigos solo usen teclas sustitutas ;-).
sleske
10
ah, no me gusta el dicho en absoluto ... las claves sustitutas también pueden ser la fuente de problemas; Sí, la aplicación será más robusta para cambiar las reglas de negocio y / o integridad, sin embargo, la información puede perderse un poco más fácilmente y la identidad de los registros se vuelve menos clara. así que no recomendaría una regla general aquí ...
Unreason
12
@onedaywhen y @jay, solo porque creas que debe ser único, no lo hagas único. Y sí, un esposo y una esposa podrían ser clientes diferentes. Solo porque no te has encontrado con esto antes no significa que no sucederá. Me he encontrado con él y sucede, por eso nunca se debe permitir que el correo electrónico se considere único, ya sea que pienses que debería serlo o no. Este es el tipo de requisito que usted rechaza porque es inherentemente incorrecto.
HLGEM
15
@HLGEM: No quiero entrar en un argumento interminable, pero no se puede decir que una clave propuesta no es única en base a hipótesis hipotéticas sin conocer el contexto. por ejemplo, desde el punto de vista de la compañía telefónica, un número de teléfono identifica de manera única a un cliente, por definición. Sí, puede decir: "¿Pero qué pasa si hay dos o tres personas que podrían responder cuando llama a ese número?" Pero esto es irrelevante. Desde el punto de vista de la compañía telefónica, por definición, este es un cliente. (continuación ...)
Jay
14
(continuación) Del mismo modo, si está creando un sistema que se ocupa en gran medida de las comunicaciones por correo electrónico, tal vez un sistema de envío de mensajes o un sistema de reenvío de notificaciones, entonces es probable que, por definición, una dirección de correo electrónico identifique de manera única a un usuario. Si varias personas comparten esa dirección de correo electrónico, eso es irrelevante. Son un único destino de mensaje, por lo tanto, son un solo usuario. "Usuario" y "cliente" no tienen que ser sinónimos de "ser humano individual".
Jay
99

la clave primaria debe ser única y constante

Las direcciones de correo electrónico cambian como las estaciones. Útil como una clave secundaria para la búsqueda, pero una mala elección para la clave primaria.

Steven A. Lowe
fuente
17
Una propiedad de una buena clave es que debe ser estable pero NO necesariamente inmutable.
día
55
@onedaywhen: ¡Sí! De lo contrario, ¿por qué SQL admitiría las actualizaciones en cascada?
Bill Karwin
18
si tiene una opción, busque claves constantes / inmutables; menos trabajo para ti en el camino; ¡solo porque SQL admite actualizaciones en cascada no significa que siempre sea una buena idea!
Steven A. Lowe
77
@Vincent Malgrat: "actualizaciones en cascada ... frenos db normalización" - ¡creo que has entendido mal el concepto de normalización!
cuando el
55
@Vincent Malgrat: gracias por confirmar que realmente has entendido mal el concepto de normalización. "no debería repetirse la misma información en varias filas" - ¿realmente quiso decir "información"? Una clave compuesta generalmente implicará valores repetidos en varias filas. Para una clave externa, los valores se referencian en lugar de "repetidos", gran diferencia. Un dominio de una sola columna con dos valores (por ejemplo, 'Sí' y 'No') tendrá los mismos valores en varias filas en una tabla de referencia si tiene tres o más filas. ¡Esto es realmente algo básico!
día
64

Desventajas de usar una dirección de correo electrónico como clave principal:

  1. Más lento al hacer uniones.

  2. Cualquier otro registro con una clave externa publicada ahora tiene un valor mayor, ocupando más espacio en disco. (Dado el costo del espacio en disco hoy en día, este es probablemente un problema trivial, excepto en la medida en que el registro ahora demore más en leerse. Ver # 1).

  3. Una dirección de correo electrónico podría cambiar, lo que obliga a actualizar todos los registros que lo utilizan como clave externa. Como la dirección de correo electrónico no cambia con tanta frecuencia, el problema de rendimiento es probablemente menor. El mayor problema es que debes asegurarte de proveerlo. Si tiene que escribir el código, esto es más trabajo e introduce la posibilidad de errores. Si su motor de base de datos admite "en cascada de actualizaciones", es un problema menor.

Ventajas de usar la dirección de correo electrónico como clave principal:

  1. Es posible que pueda eliminar por completo algunas uniones. Si todo lo que necesita del "registro maestro" es la dirección de correo electrónico, entonces con una clave entera abstracta, tendría que hacer una unión para recuperarlo. Si la clave es la dirección de correo electrónico, entonces ya la tiene y la unión es innecesaria. Si esto le ayuda en algo depende de la frecuencia con la que surja esta situación.

  2. Cuando realiza consultas ad hoc, es fácil para un ser humano ver a qué registro maestro se hace referencia. Esto puede ser de gran ayuda cuando se trata de rastrear problemas de datos.

  3. Es casi seguro que necesitará un índice en la dirección de correo electrónico de todos modos, por lo que al ser la clave principal se elimina un índice, lo que mejora el rendimiento de las inserciones, ya que ahora solo tienen un índice para actualizar en lugar de dos.

En mi humilde opinión, no es un slam-dunk de ninguna manera. Tiendo a preferir el uso de claves naturales cuando hay una práctica disponible porque son más fáciles de trabajar y las desventajas tienden a no importar mucho en la mayoría de los casos.

Arrendajo
fuente
@Conrad: Sin embargo, él señala que no es un PITA si tiene un motor compatible con ON UPDATE CASCADE. No es un problema en ese punto en cuanto a código; El único problema real es qué tan extensa es la actualización y qué tan amplia es la clave. La dirección de correo electrónico puede ser demasiado, pero una ACTUALIZACIÓN EN CASCADA para un PK de código de país de 2 caracteres no es gran cosa.
Matthew Wood
55
@ Matthew IMHO sigue siendo una PITA. Por ejemplo, suponga que cuando diseñó la tabla de su país, solo había dos tablas que la hacían referencia, sin importancia, pero con el tiempo se convirtieron en 20 tablas cada una con cientos de miles de registros. Algunos con la referencia algunos sin. Esto hace que una única escritura lógica termine siendo decenas de miles de escrituras, y no llega a todas las tablas porque alguien olvidó una referencia cuando agregó la tabla. Esto es exactamente lo que me pasó en una tabla de códigos de país de 2 caracteres.
Conrad Frix
@Wood & Conrad: El peor de los casos es cuando no hay soporte de DB incorporado. Luego, tiene que escribir el código para cada tabla con una referencia publicada, y esto es solo una molestia y una puerta para que se introduzcan los errores. Con las cascadas, solo debe recordar agregar una cláusula en cada tabla, no un gran problema.
Jay
2
Las ventajas 1 y 3 son optimizaciones prematuras, la ventaja 2 es un beneficio muy pequeño y cualquier herramienta de consulta decente la supera por completo.
Ash
44
@ Ash: Thee es una diferencia entre "optimizatin" y "optimización prematura". Pero bueno, por el mismo razonamiento, todas las desventajas que he visto mencionar son optimizaciones prematuras. Entonces, ¿dónde te deja eso? En cuanto al n. ° 2, creo que escribir combinaciones adicionales al intentar hacer consultas ad hoc es un gran problema. Los registros a menudo tienen varias claves externas, por lo que es posible que necesite varias combinaciones para obtener datos comprensibles. Si por "herramienta de consulta decente" te refieres a uno que descubre qué datos quieres ver sin que lo digas y mágicamente hace las uniones por ti, me gustaría ver cómo funciona.
Jay
12

Es bastante malo Suponga que algún proveedor de correo electrónico cierra. Los usuarios querrán cambiar su correo electrónico. Si ha utilizado el correo electrónico como clave principal, todas las claves externas para los usuarios duplicarán ese correo electrónico, lo que hace que sea muy difícil de cambiar ...

... y ni siquiera he comenzado a hablar sobre consideraciones de rendimiento.

Meriton
fuente
¿Cómo cambiaría las direcciones de correo electrónico si hubiera duplicados? A menos que el usuario A cambie su dirección de correo electrónico, y luego el usuario B cambie su correo electrónico para que sea el mismo que el valor anterior del usuario A, y sus actualizaciones no se realizarán en secuencia. Remotamente posible, supongo.
Jay
2
Una referencia de clave externa, por definición, contiene el valor de la clave primaria de la fila a la que hace referencia. Dicho de otra manera, duplica el valor de la clave primaria. (Por lo tanto, la duplicación no es causada por el cambio del valor. Pero el cambio es más difícil debido a esta duplicación y a la restricción que la impone).
meriton
55
+1 para la línea "Suponga que algún proveedor de correo electrónico cierra".
Reddy
Esto no es un problema. Existe una cascada de claves foráneas para resolver este problema. Si un usuario cambia su correo electrónico, el cambio se aplicará en cascada a todas las tablas que lo usan como clave externa.
Rafa
1
@rafa, le aseguro que si usa actualizaciones en cascada y todo un proveedor cierra o cambia su nombre (Yahoo.com se convierte en HooYa.com), su base de datos estará bloqueada a todos los usuarios durante horas y tal vez días mientras esta en cascada a través del sistema. Es un problema muy válido (y una razón por la cual es una mala idea usar actualizaciones en cascada si tiene una cantidad significativa de datos y es probable que la clave cambie).
HLGEM
12

No sé si eso podría ser un problema en su configuración, pero dependiendo de su RDBMS, los valores de una columna pueden ser sensibles a mayúsculas y minúsculas . Los documentos de PostgreSQL dicen: "Si declara una columna como ÚNICA o CLAVE PRIMARIA, el índice generado implícitamente distingue entre mayúsculas y minúsculas". En otras palabras, si acepta la entrada del usuario para una búsqueda en una tabla con el correo electrónico como clave principal y el usuario proporciona "[email protected]", no encontrará "[email protected]".

xlttj
fuente
77
Vale la pena mencionar a este respecto que [email protected] y [email protected] pueden ser el mismo buzón o pueden ser buzones diferentes y no tiene forma de saberlo: no hay nada en la especificación que indique si la parte local es mayúscula o minúscula. sensible.
Telent
Este es un problema más general con la aplicación exclusiva de las direcciones de correo electrónico en lugar de si deben usarse como claves principales; el mismo problema existe de cualquier manera. +1 porque sigue siendo un punto muy útil
11

Nadie parece haber mencionado un posible problema de que las direcciones de correo electrónico puedan considerarse privadas. Si la dirección de correo electrónico es la clave principal, lo más probable es que la URL de una página de perfil tenga un aspecto similar ..../Users/[email protected]. ¿Qué sucede si no desea exponer la dirección de correo electrónico del usuario? Tendría que encontrar otra forma de identificar al usuario, posiblemente mediante un valor entero único para hacer que las URL sean similares ..../Users/1. Entonces terminarías con un valor entero único después de todo.

Simen Echholt
fuente
9

En el nivel lógico , el correo electrónico es la clave natural. En el nivel físico , dado que está utilizando una base de datos relacional, la clave natural no encaja bien como clave principal. La razón es principalmente los problemas de rendimiento mencionados por otros.

Por esa razón, el diseño se puede adaptar. La clave natural se convierte en la clave alternativa (ÚNICA, NO NULA), y utiliza una clave sustituta / artificial / técnica como clave principal, que puede ser un incremento automático en su caso.

systemmpuntoout preguntó,

¿Qué pasa si alguien quiere cambiar su dirección de correo electrónico? ¿Vas a cambiar todas las claves foráneas también?

Para eso es en cascada .

Otra razón para usar una clave sustituta numérica como clave principal está relacionada con el funcionamiento de la indexación en su plataforma. En InnoDB de MySQL, por ejemplo, todos los índices de una tabla tienen la clave principal preestablecida, por lo que desea que la PK sea lo más pequeña posible (por razones de velocidad y tamaño). También relacionado con esto, InnoDB es más rápido cuando la clave primaria se almacena en secuencia, y una cadena no ayudaría allí.

Otra cosa a tener en cuenta al usar una cadena como una clave alternativa es que usar un hash de la cadena real que desea puede ser más rápido, omitiendo elementos como mayúsculas y minúsculas de algunas letras. (De hecho, aterricé aquí mientras buscaba una referencia para confirmar lo que acabo de decir; todavía busco ...)

Rafa
fuente
5

Sí, es una clave primaria incorrecta porque sus usuarios querrán actualizar sus direcciones de correo electrónico.

Bryan Legend
fuente
1
Pensé en señalar que ahora tenemos una cascada, esto no es un problema
malhal
4

sí, es mejor si usas un entero en su lugar. También puede configurar su columna de correo electrónico como restricción única.

Me gusta esto:

CREATE TABLE myTable(
    id integer primary key,
    email text UNIQUE
);
ibram
fuente
8
¿Por qué es "mejor"? ¿Alguna razón o fuente?
Sjoerd
20
Puedes profundizar sobre eso?
Sjoerd
3

Otra razón por la cual la clave primaria entera es mejor es cuando se refiere a la dirección de correo electrónico en una tabla diferente. Si la dirección en sí es una clave principal, en otra tabla debe usarla como clave. Así que almacenas direcciones de correo electrónico varias veces.

klew
fuente
3

No estoy muy familiarizado con los postgres. Primary Keys es un gran tema. He visto algunas excelentes preguntas y respuestas en este sitio (stackoverflow.com).

Creo que puede tener un mejor rendimiento al tener una clave primaria numérica y usar un ÍNDICE ÚNICO en la columna de correo electrónico. Los correos electrónicos tienden a variar en longitud y pueden no ser adecuados para el índice de clave principal.

Un poco de lectura aquí y aquí.

Saif Khan
fuente
3

Personalmente, no utilizo ninguna información para la clave principal cuando diseño la base de datos, porque es muy probable que necesite modificar cualquier información más adelante. La única razón por la que proporciono la clave primaria es que es conveniente realizar la mayoría de las operaciones de SQL desde el lado del cliente, y mi elección para eso siempre ha sido el tipo entero de incremento automático.

tia
fuente
2

Su colega tiene razón: use un entero de incremento automático para su clave principal.

Puede implementar la unicidad del correo electrónico a nivel de aplicación, o puede marcar su columna de dirección de correo electrónico como única y agregar un índice en esa columna.

Agregar el campo como único le costará la comparación de cadenas solo cuando se inserte en esa tabla, y no cuando realice uniones y comprobaciones de restricciones de clave externa.

Por supuesto, debe tener en cuenta que agregar restricciones a su aplicación a nivel de base de datos puede hacer que su aplicación se vuelva inflexible. Siempre preste la debida consideración antes de hacer cualquier campo "único" o "no nulo" solo porque su aplicación necesita que sea único o no esté vacío.

jrharshath
fuente
1
"Siempre considere debidamente antes de implementar el requisito x solo porque su aplicación necesita el requisito x". - El peor consejo que he leído en bastante tiempo.
día
Su "argumento" no me convence: en la vida real a menudo habrá situaciones en las que algunos datos esenciales (por ejemplo, un número de teléfono) no estarán disponibles de inmediato. Si dicho campo está marcado como NOT NULL en una base de datos, requerirá que los usuarios contaminen los datos con campos ficticios (como 123) en lugar de dejarlos vacíos. Sería más práctico dejar que la aplicación maneje las restricciones (y en este caso, la aplicación podría marcar un campo vacío como elemento de acción).
jrharshath
55
Estoy de acuerdo en que la definición de un campo "no nulo" debe hacerse con cautela. Requisitos como "siempre necesitamos el número de teléfono del cliente" deben considerarse cuidadosamente. ¿No sería deseable a veces crear un registro de cliente a pesar de que no sabemos el número de teléfono en este momento, y regresar y obtenerlo más tarde? Pero "este campo debe ser único" es una categoría diferente. No puedo imaginar decir "Está bien que dos empleados tengan el mismo número de seguro social, lo resolveremos más tarde". ¿Cómo enderezarías los datos?
Jay
1
Be Wolves: una vez conocí a una mujer que no tenía su propio número de teléfono. ¿Que haces entonces?
David Thornley, el
@DavidThornley Parece que debería hacer más ejercicio, o tal vez adaptar un comportamiento más amigable.
Philip Schiff
2

Use un GUID como clave principal ... de esa manera puede generarlo desde su programa cuando hace un INSERT y no necesita obtener una respuesta del servidor para averiguar cuál es la clave primaria. También será único en todas las tablas y bases de datos y no tendrá que preocuparse por lo que suceda si trunca la tabla algún día y el incremento automático se restablece a 1.

JoelFan
fuente
2
A menos que le importe poco o nada el rendimiento, use un GUID. Es no-no # 1 si está construyendo un sistema que tendrá que escalar
Micah
no ... ver davybrion.com/blog/2009/05/…
JoelFan
3
Dicho en la verdadera moda de beber de Microsoft-Kool-Aid!
Gary Chambers el
2

Sé que esta entrada es un poco tardía, pero me gustaría agregar que las personas abandonan las cuentas de correo electrónico y los proveedores de servicios recuperan la dirección permitiendo que otra persona la use.

Como señaló @HLGEM "[email protected] puede pertenecer fácilmente a John Smith un año y a Julia Smith dos años después". en este caso, si John Smith quiere su servicio, debe negarse a usar su dirección de correo electrónico o eliminar todos sus registros relacionados con Julia Smith.

Si tiene que eliminar registros y se relacionan con el historial financiero de la empresa, según la ley local, podría encontrarse en apuros.

Por lo tanto, nunca usaría datos como direcciones de correo electrónico, placas de matrícula, etc., como claves principales, porque no importa cuán únicos parezcan estar fuera de su control y pueden proporcionar algunos desafíos interesantes con los que puede que no tenga tiempo para lidiar.

Robert
fuente
2

Es posible que deba considerar cualquier legislación de regulación de datos aplicable. El correo electrónico es información personal, y si sus usuarios son ciudadanos de la UE, por ejemplo, bajo GDPR pueden indicarle que elimine su información de sus registros (recuerde que esto se aplica independientemente del país en el que se encuentre).

Si necesita mantener el registro en la base de datos por integridad referencial o por razones históricas como la auditoría, el uso de una clave sustituta le permitiría simplemente NULAR todos los campos de datos personales. Obviamente, esto no es tan fácil si sus datos personales son la clave principal

Stuart Parker
fuente
1

puede aumentar el rendimiento utilizando la clave primaria entera.

xport
fuente
1

debes usar una clave primaria entera. Si necesita que la columna de correo electrónico sea única, ¿por qué no establece simplemente un índice único en esa columna?

oezi
fuente
1

Si tiene un valor no int como clave principal, las inserciones y recuperaciones serán muy lentas en datos grandes.

Amareswar
fuente
1
No, las inserciones serán más lentas porque necesita dos índices únicos: uno en la clave primaria generada y otro en la dirección de correo electrónico.
a_horse_with_no_name
1

La clave primaria debe elegirse como un atributo estático. Dado que las direcciones de correo electrónico no son estáticas y pueden ser compartidas por múltiples candidatos, no es una buena idea usarlas como clave principal. Además, las direcciones de correo electrónico son cadenas de una cierta longitud que pueden ser mayores que la identificación única que nos gustaría usar [len (dirección_de_email)> len (id_unica)] por lo que requeriría más espacio e incluso peor, se almacenan varias veces como clave externa . Y, en consecuencia, conducirá a degradar el rendimiento.

usuario2719152
fuente
0

Depende de la mesa. Si las filas en su tabla representan direcciones de correo electrónico, entonces el correo electrónico es la mejor identificación. Si no, entonces el correo electrónico no es una buena identificación.

Lajos Arpad
fuente
0

Si se trata simplemente de exigir que el correo electrónico sea único, puede crear un índice único con esa columna.

Micah
fuente
0

El correo electrónico es un buen candidato de índice único, pero no para la clave principal, si es una clave principal, no podrá cambiar la dirección de correo electrónico del contacto, por ejemplo. Creo que sus consultas de unión también serán más lentas.

Chocolim
fuente
0

no use la dirección de correo electrónico como clave principal, mantenga el correo electrónico como único pero no lo use como clave principal, use la identificación de usuario o el nombre de usuario como clave principal

Nikki
fuente