В каком типе данных я должен хранить адрес электронной почты в базе данных?


44

Я понимаю, что адрес электронной почты из 254 символов действителен, но исследованные мною реализации, как правило, используют от varchar (60) до varchar (80) или его эквивалент. Например: эта рекомендация SQL Server использует varchar (80) или этот пример Oracle

Есть ли причина не использовать максимум 254 символа? Разве varchar по определению не использует столько памяти, сколько необходимо для хранения данных?

Существуют ли существенные последствия / компромиссы для производительности, которые заставляют так много реализаций использовать меньше, чем полные 254 возможных символа?

Ответы:


45

Я всегда использовал VARCHAR(320). Вот почему Стандарт диктует следующие ограничения:

  • 64 символа для «локальной части» (имя пользователя).
  • 1 символ для @символа.
  • 255 символов для доменного имени.

Теперь, некоторые люди скажут, что вам нужно поддерживать больше, чем это. Некоторые люди также скажут, что вам нужно поддерживать Unicode для доменных имен (то есть вы должны переключиться на NVARCHAR). В то время как стандарт может измениться в это время (прошло много времени с тех пор, как у меня был скин в игре), я вполне уверен, что в настоящее время большинство серверов в мире не будут принимать адреса электронной почты Unicode, и я уверен, у многих серверов возникнут проблемы при создании и / или принятии адресов длиной более 320 символов.

Тем не менее, вы можете подготовиться к худшему сейчас, если хотите (и если вы используете сжатие данных в SQL Server 2008 R2 или выше, вы получите выгоду от сжатия Unicode, то есть вы платите только 2-байтовый штраф за символы, которые действительно нужны Это). Таким образом, вы можете сделать вашу колонку настолько широкой, насколько вы хотите, и вы можете позволить людям загружать туда любой слишком длинный мусор, который они хотят - они не получат электронное письмо, если они будут давать вам барахло так же, как они не будут получить электронную почту, если вставка не удалась. Проблема в том, что если вы пропустите недействительный мусор, выприходится иметь дело с этим. И независимо от того, какого размера вы его сделаете - если кто-то попытается вставить 400 символов в столбец из 320 символов, кто-то попытается вставить 1025 символов в столбец из 1024 символов. Нет причин, по которым любой разумный человек должен иметь адрес электронной почты> 320 символов, если только он не использует его для явного тестирования системных границ.

Но перестаньте спрашивать мнения по этому поводу - и перестаньте смотреть на другие реализации для руководства (просто так в этом случае, что те, на кого вы ссылались, не удосужились сделать свою домашнюю работу и просто выбрали номера из своих, ну, вы знаете) , У вас есть прямой доступ к стандарту - убедитесь, что вы обращаетесь к самой последней версии, поддерживаете ее как минимум и остаетесь на вершине стандарта, чтобы вы могли адаптироваться к изменениям в спецификациях.


РЕДАКТИРОВАТЬ благодаря @ypercube за пинг в чате.

Кроме того, возможно, вы не хотите в первую очередь сваливать весь адрес в один столбец. Нормализация может указывать на то, что вы не хотите хранить @hotmail.com15 миллионов раз, когда гораздо более тонкий FK int будет работать просто отлично и не иметь дополнительных издержек на столбцы переменной длины. Вы также можете нормализовать имя пользователя, как john.smith@hotmail.comи john.smith@gmail.comразделить общее имя пользователя - они не знают друг друга, но ваша база данных не заботится об этом.

Я говорил об этом здесь:

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/

Это, однако, создает проблемы для вышеуказанного предела в 254 символа, поскольку, похоже, нет единого мнения о том, что происходит, когда действительный домен из 255 символов объединяется с допустимым локальным разделом из 1 символа. Это должно быть принято большинством серверов по всему миру, но, похоже, нарушает этот предел в 254 символа. Итак, вы создаете Domainsтаблицу с искусственно меньшим ограничением длины для адресов электронной почты, когда домен может быть повторно использован в качестве действительного 255-символьного URL?


Мне нравится этот подход, но как насчет уникальности электронной почты? Как это управляется?
Роберто Рицци

2
@RobertoRizzi Уникальное ограничение или первичный ключ для комбинации DomainID + LocalPart или наоборот.
Аарон Бертран

5

Есть несколько соображений с этим решением. Прежде всего, следует использовать текущие и будущие прогнозы необходимых ограничений, которым должны будут соответствовать данные. Есть причина, почему вы не хотите устанавливать каждый тип данных столбца строки, varchar(1024)когда вы просто храните строку, длина которой не должна превышать 32 символа (акцент на ключевом слове should ).

Если у вас есть какая-то уязвимость, когда все электронные письма изменяются и превращаются в 255 символов, это может привести к длительному снижению производительности разбиения страниц. Это может показаться необычным, и, скорее всего, так и есть, но вам необходимо настроить данные в соответствии с требованиями бизнеса . Подобно вековым ограничениям в дискуссии о базе данных и приложениях, я твердо убежден в том, что ограничения и допустимые значения типов данных также должны применяться на уровне данных.

Что приводит меня к следующему пункту. База данных, скорее всего, просто уровень данных. Что использует уровень приложения? Например, если у вас есть приложение, в котором вы можете ввести только 80 символов для адреса электронной почты, почему вы хотите, чтобы тип данных был больше? Бизнес должен ответить на два вопроса:

  1. Что это может быть?
  2. Что это должно быть?

Только тогда вы получите ответ.

Разве varchar по определению не использует столько памяти, сколько необходимо для хранения данных?

Да и нет. Там будет своего рода смещение для данных переменной длины, чтобы записать их длину.


3

RFC 5321 (текущая спецификация SMTP, устаревшие RFC2821) гласит:

Максимальная общая длина имени пользователя или другой локальной части составляет 64 октета. Максимальная общая длина доменного имени или номера составляет 255 октетов.

Таким образом, знак 64 + 255 + @ означает VARCHAR (320). Вам, вероятно, никогда не понадобится так много, но это безопасно, на всякий случай.



1

Любая вариация VARCHAR использует только столько места в блоке данных, сколько необходимо. Дополнительные байты для хранения длины тривиальны по сравнению с пространством, которое было бы потрачено впустую при использовании CHAR фиксированной длины.

Поскольку длина столбца VARCHAR действительно является «максимальной длиной», она должна быть больше максимальной возможной длины при любых обстоятельствах. Будет использовано только столько места, сколько нужно каждому ряду. Затем прикладные программы должны быть разработаны с полями прокрутки или чем-то еще, что имеет смысл на основе типичных значений.

Дизайн базы данных похож на физический лист бумаги в том смысле, что он устанавливает жесткие ограничения по размеру. Бумажная страница не может быть увеличена. В этой аналогии прикладная программа похожа на форму, напечатанную на странице. Можно многое сделать, чтобы настроить объем данных, которые мы можем хранить в форме.

Хотя команда для увеличения размера VARCHAR может показаться простой и мгновенно выполняемой для небольшой таблицы, выполнение этого для таблицы с тысячами строк или более, вероятно, потребует некоторого приостановки работы базы данных при регенерации всех блоков данных и индексов. Один из способов - скопировать все в новую таблицу с большими столбцами. Какая бы техника ни использовалась, это очень сложная сделка. Таким образом, вы должны учитывать, что размер столбца VARCHAR в значительной степени неизменен после загрузки рабочей таблицы.


1

В качестве комментария к отличным ответам уже здесь:

Во-первых, если вы создали поле как varchar(240)и хотите позже изменить его на более длинное поле, скажем varchar(320), это изменение должно быть тривиальной операцией на сервере базы данных - в зависимости, конечно, от вашего продукта базы данных.

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

Во-вторых, в зависимости от среднего размера строки и размера страницы использование varchar(320)вместо varchar(240)может не изменить количество выделенных страниц (дисковое пространство, фактически занятое таблицей).

В-третьих, кто-то выше говорил о проверке адреса электронной почты. Я утверждаю, что существует только один верный способ подтвердить адрес электронной почты, а именно отправить ему электронное письмо. :-)


0

VARCHAR - это лучший тип данных, который будет использоваться для адресов электронной почты, так как электронные письма сильно различаются по длине. NVARCHAR также является альтернативой, но я бы порекомендовал использовать его только в том случае, если адрес электронной почты содержит расширенные символы и имейте в виду, что он требует двойного объема памяти по сравнению с VARCHAR.

В моем окружении мы используем varchar (70), так как самые длинные, с которыми я сталкивался, имеют длину 60–70 символов, но это также зависит от клиентской базы вашей компании. Кроме того, в качестве дополнительного примечания, убедитесь, что у вас есть некоторая проверка проверки электронной почты на месте для проверки правильности адресов электронной почты .. как, например, использование проверочных ограничений или CHARINDEX.


0

Использование SQL DOMAIN

Если вы используете сервер базы данных предприятия, должно быть какое-то место для хранения адреса электронной почты DOMAINс некоторым уровнем достоверности. Домены указаны в спецификации SQL

Домен - это именованный пользовательский объект, который может быть указан как альтернатива типу данных в определенных местах, где может быть указан тип данных. Домен состоит из типа данных, возможно, опции по умолчанию и нулевых или более (доменных) ограничений.

Например, свободный и открытый исходный код PostgreSQL поддерживает это, за исключением любых ограничений в реализации спецификации, сам столбец содержит действительный адрес электронной почты. Вы можете, например ..

  • Создайте пользовательскую DOMAINспецификацию электронной почты в HTML5.
  • Или по спецификации RFC822, RFC2822, RFC5322 электронной почты.
  • Создайте кастом, DOMAINкоторый проверяет сервер на наличие MX-записи во время проверки.

Я оцениваю эти варианты в этом ответе, который специфичен для PostgreSQL

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.