¿En qué tipo de datos debo almacenar una dirección de correo electrónico en la base de datos?

44

Entiendo que una dirección de correo electrónico de 254 caracteres es válida, pero las implementaciones que he investigado tienden a usar un varchar (60) a varchar (80) o equivalente. Por ejemplo: esta recomendación de SQL Server usa varchar (80) o este ejemplo de Oracle

¿Hay alguna razón para no usar el máximo de 254 caracteres como máximo? ¿Un varchar, por definición, usa solo la cantidad de almacenamiento necesario para almacenar los datos?

¿Existen implicaciones / compensaciones de rendimiento significativas que causen que tantas implementaciones utilicen menos de los 254 caracteres posibles?

Thronk
fuente

Respuestas:

45

Siempre he usado VARCHAR(320). Este es el por qué. El estándar dicta las siguientes limitaciones:

  • 64 caracteres para la "parte local" (nombre de usuario).
  • 1 carácter para el @símbolo.
  • 255 caracteres para el nombre de dominio.

Ahora, algunas personas dirán que necesitas apoyar más que eso. Algunas personas también dirán que debe admitir Unicode para los nombres de dominio (lo que significa que debe cambiar a NVARCHAR). Si bien el estándar puede cambiar mientras tanto (ha pasado un tiempo desde que tuve la máscara en el juego), estoy bastante seguro de que en este momento la mayoría de los servidores del mundo no aceptarán direcciones de correo electrónico Unicode, y estoy seguro muchos servidores tendrán problemas para crear y / o aceptar direcciones con> 320 caracteres.

Dicho esto, puede prepararse para lo peor ahora, si lo desea (y si está utilizando Compresión de datos en SQL Server 2008 R2 o superior, se beneficiará de la compresión Unicode, lo que significa que solo paga la penalización de 2 bytes por los caracteres que realmente necesitan eso). De esta manera, puede hacer que su columna sea lo más amplia que desee, y puede dejar que la gente llene cualquier basura demasiado larga allí que quieran; no recibirán un correo electrónico si le dan basura como no lo harán. recibir un correo electrónico si falla la inserción. El problema es que si se deja basura válida en, ustedtiene que lidiar con eso. Y no importa de qué tamaño lo hagas: si alguien intenta meter 400 caracteres en una columna de 320 caracteres, alguien intentará meter 1025 caracteres en una columna de 1024 caracteres. No hay ninguna razón por la que una persona sensata deba tener una dirección de correo electrónico> 320 caracteres a menos que la esté usando para probar explícitamente los límites del sistema.

Pero deje de pedir opiniones sobre esto, y deje de buscar otras implementaciones para obtener orientación (solo sucede que en este caso las que mencionó no se molestaron en hacer su propia tarea y simplemente seleccionaron números de sus, bueno, ya sabes) . Tiene acceso directo al estándar : asegúrese de consultar la versión más reciente, admitirlo como mínimo y mantenerse al tanto del estándar para que pueda adaptarse a los cambios en las especificaciones.


EDITAR gracias a @ypercube por el ping en el chat.

Como comentario, quizás no desee volcar la dirección completa en una sola columna en primer lugar. La normalización puede sugerir que no desea almacenar @hotmail.com15 millones de veces cuando un FK int mucho más delgado funcionaría bien y no tendría la sobrecarga adicional de las columnas de longitud variable. También puede normalizar el nombre de usuario [email protected]y [email protected]compartir un nombre de usuario común: no se conocen pero a su base de datos no le importa.

Hablé sobre algo de esto aquí:

http://www.mssqltips.com/sqlservertip/2657/storing-email-addresses-more-efficiently-in-sql-server/

http://www.mssqltips.com/sqlservertip/2671/storing-email-addresses-more-efficiently-in-sql-server--part-2/

Sin embargo, esto presenta desafíos al límite de 254 caracteres anterior, ya que no parece haber consenso sobre lo que sucede cuando un dominio válido de 255 caracteres se combina con una parte local válida de 1 carácter. Esto debería ser aceptado por la mayoría de los servidores de todo el mundo, pero parece violar este límite de 254 caracteres. Entonces, ¿creas una Domainstabla que tenga una restricción artificialmente menor en la longitud de las direcciones de correo electrónico, cuando el dominio podría reutilizarse como una URL válida de 255 caracteres?

Aaron Bertrand
fuente
Me gusta este enfoque, pero ¿qué pasa con la singularidad del correo electrónico? ¿Cómo se gestiona?
Roberto Rizzi
2
@RobertoRizzi Una restricción única o clave principal en la combinación de DomainID + LocalPart o viceversa.
Aaron Bertrand
5

Hay algunas consideraciones con esta decisión. Lo primero y más importante es utilizar las predicciones actuales y futuras de las limitaciones necesarias que los datos deberán cumplir. Hay una razón por la que no desea establecer cada tipo de datos de columna de cadena varchar(1024)cuando solo está almacenando una cadena que no debe exceder los 32 caracteres (énfasis en la palabra clave should ).

Si tiene algún tipo de vulnerabilidad donde los correos electrónicos se modifican para convertirse en 255 caracteres, entonces podría tener un impacto prolongado en el rendimiento de las divisiones de página. Esto puede parecer fuera de lo común, y lo más probable es que sea así, pero debe dimensionar sus datos según los requisitos comerciales . Al igual que la antigua restricción en el debate de la base de datos frente a la aplicación, creo firmemente que las limitaciones del tipo de datos y los valores permitidos también deberían aplicarse en el nivel de datos.

Lo cual me lleva a mi siguiente punto. Lo más probable es que la base de datos sea solo el nivel de datos. ¿Qué utiliza el nivel de aplicación? Por ejemplo, si tiene una aplicación donde solo puede ingresar 80 caracteres para una dirección de correo electrónico, ¿por qué desea que el tipo de datos sea más grande? Las empresas deben responder dos preguntas:

  1. Que puede ser
  2. Que debe ser

Solo entonces tendrás tu respuesta.

¿Un varchar, por definición, usa solo la cantidad de almacenamiento necesario para almacenar los datos?

Si y no. Habrá una especie de desplazamiento para los datos de longitud variable para registrar la longitud de los mismos.

Thomas Stringer
fuente
3

RFC 5321 (la especificación SMTP actual, obsoletos RFC2821) establece:

La longitud total máxima de un nombre de usuario u otra parte local es de 64 octetos. La longitud total máxima de un nombre de dominio o número es 255 octetos

Entonces el signo 64 + 255 + @ implica VARCHAR (320). Probablemente nunca necesite tanto, pero es seguro tenerlo, por si acaso.

avakharia
fuente
44
El límite correcto es 254. rfc-editor.org/errata_search.php?rfc=3696&eid=1690
Neil McGuigan
1

Cualquier variación de VARCHAR usa solo tanto espacio en el bloque de datos como sea necesario. Los bytes adicionales para almacenar la longitud son triviales en comparación con el espacio que se desperdiciaría utilizando un CHAR de longitud fija.

Dado que una longitud de columna VARCHAR es realmente una "longitud máxima", debe establecerse más grande que la longitud máxima posible bajo cualquier circunstancia. Solo se utilizará tanto espacio como necesite cada fila. Los programas de aplicación deben diseñarse con campos de desplazamiento o lo que tenga sentido en función de los valores típicos.

El diseño de una base de datos es como un papel físico en el que establece los límites estrictos en cuanto al tamaño. Una página de papel no puede ampliarse. En esta analogía, el programa de aplicación es como un formulario impreso en la página. Se puede hacer mucho para ajustar la cantidad de datos que podemos contener en el formulario.

Aunque el comando para aumentar el tamaño de VARCHAR puede parecer simple y ejecutarse instantáneamente en una tabla pequeña, hacerlo en una tabla con miles de filas o más probablemente requerirá algún tipo de inactividad de la base de datos mientras se regeneran todos los bloques de datos e índices. Una forma es copiar todo a una nueva tabla con las columnas más grandes. Cualquiera que sea la técnica utilizada, es un gran negocio. Por lo tanto, debe considerar el tamaño de la columna VARCHAR en gran medida inmutable una vez que se carga una tabla de producción.

DocSalvager
fuente
1

Como comentario a las excelentes respuestas que ya están aquí:

Primero, si ha creado el campo como varchar(240)y desea cambiarlo luego a un campo más largo, por ejemplo varchar(320), este cambio debería ser una operación trivial en el servidor de la base de datos, dependiendo, por supuesto, de su producto de base de datos.

alter table Schema.Object alter column EmailAddress varchar(320) ;

En segundo lugar, según el tamaño de fila promedio y el tamaño de página, el uso en varchar(320)lugar de varchar(240)no puede cambiar el número de páginas asignadas (el espacio en disco realmente ocupado por la tabla).

Tercero, alguien de arriba habló sobre validar una dirección de correo electrónico. Sostengo que solo hay una forma segura de validar una dirección de correo electrónico y es enviarle un correo electrónico. :-)

Caminante de piedra verde
fuente
0

VARCHAR es el mejor tipo de datos que se utilizará para las direcciones de correo electrónico, ya que los correos electrónicos varían mucho según la longitud. NVARCHAR también es una alternativa, pero recomendaría que se use solo si la dirección de correo electrónico contiene caracteres extendidos y tenga en cuenta que requiere una cantidad doble de espacio de almacenamiento en comparación con VARCHAR.

En mi entorno, utilizamos varchar (70), ya que los más largos con los que me he encontrado tienen cerca de 60-70 char de largo, pero también depende de la base de clientes de su empresa. Además, como nota al margen, asegúrese de tener alguna verificación de validación de correo electrónico en el lugar para la validez de las direcciones de correo electrónico ... como usar restricciones de verificación o CHARINDEX

Kin Shah
fuente
0

Usando SQL DOMAIN

Si está utilizando un servidor de base de datos de empresa, debería haber alguna forma de almacenar una dirección de correo electrónico DOMAINcon cierto nivel de validez. Los dominios se especifican en la especificación SQL

Un dominio es un objeto definido por el usuario con nombre que se puede especificar como alternativa a un tipo de datos en ciertos lugares donde se puede especificar un tipo de datos. Un dominio consta de un tipo de datos, posiblemente una opción predeterminada, y cero o más restricciones (dominio).

Por ejemplo, el PostgreSQL gratuito y de código abierto lo admite, salvo restricciones en la implementación de la especificación, la columna en sí contiene un correo electrónico válido. Puedes por ejemplo ...

  • Cree una DOMAINespecificación de correo electrónico personalizada sobre HTML5.
  • O, a través de la especificación de correo electrónico RFC822, RFC2822, RFC5322.
  • Cree una costumbre DOMAINque verifique que el servidor tenga un registro MX en el momento de la verificación.

Evalúo estas opciones en esta respuesta que es específica de PostgreSQL

Evan Carroll
fuente