W jakim typie danych powinienem przechowywać adres e-mail w bazie danych?

44

Rozumiem, że adres e-mail o długości 254 znaków jest prawidłowy, ale implementacje, które badałem, zwykle używają varchar (60) do varchar (80) lub odpowiednika. Na przykład: to zalecenie programu SQL Server używa varchar (80) lub tego przykładu Oracle

Czy istnieje powód, aby nie używać maksymalnie 254 znaków? Czy varchar z definicji nie używa tyle pamięci, ile jest potrzebne do przechowywania danych?

Czy istnieją znaczące implikacje wydajnościowe / kompromisy, które powodują, że tak wiele implementacji używa mniej niż pełnych 254 możliwych znaków?

Thronk
źródło

Odpowiedzi:

45

Zawsze używałem VARCHAR(320). Dlatego. Norma określa następujące ograniczenia:

  • 64 znaki dla „części lokalnej” (nazwa użytkownika).
  • 1 znak dla @symbolu.
  • 255 znaków dla nazwy domeny.

Teraz niektórzy ludzie powiedzą, że potrzebujesz więcej wsparcia. Niektórzy powiedzą również, że musisz obsługiwać Unicode dla nazw domen (co oznacza, że ​​musisz się przełączyć NVARCHAR). Chociaż w międzyczasie standard może się zmienić (minęło trochę czasu, odkąd mam skórkę w grze), jestem całkiem pewien, że w tej chwili większość serwerów na świecie nie akceptuje adresów e-mail Unicode i jestem pewien wiele serwerów będzie miało problemy z tworzeniem i / lub akceptowaniem adresów zawierających> 320 znaków.

To powiedziawszy, możesz teraz przygotować się na najgorsze, jeśli chcesz (a jeśli używasz kompresji danych w SQL Server 2008 R2 lub lepszej, skorzystasz z kompresji Unicode, co oznacza, że ​​płacisz tylko 2 bajty kary za znaki, które faktycznie potrzebują to). W ten sposób możesz ustawić kolumnę tak szeroką, jak chcesz, i pozwolić innym na umieszczanie tam zbyt długich śmieci, których chcą - nie otrzymają wiadomości e-mail, jeśli podadzą ci śmieci tak, jak tego nie zrobią otrzymać e-mail, jeśli wkładka nie powiedzie się. Problemem jest to, jeśli pozwolisz, nieprawidłową śmieci w ciebiemuszę sobie z tym poradzić. I bez względu na to, jaki rozmiar wybierzesz - jeśli ktoś spróbuje upchnąć 400 znaków w kolumnie o długości 320 znaków, ktoś spróbuje upchnąć 1025 znaków w kolumnie o długości 1024 znaków. Nie ma powodu, aby jakakolwiek rozsądna osoba miała adres e-mail> 320 znaków, chyba że używa go do jawnego testowania granic systemu.

Ale przestańcie pytać o opinie na ten temat - i przestańcie szukać innych implementacji w celu uzyskania wskazówek (tak się dzieje w tym przypadku, że te, o których wspominaliście, nie zadawali sobie trudu, aby odrobić pracę domową i po prostu wybrali numery z ich, no cóż, wiesz) . Masz bezpośredni dostęp do standardu - koniecznie zapoznaj się z najnowszą wersją, obsługuj ją jako minimum i bądź na bieżąco z normą, aby dostosować się do zmian w specyfikacji.


EDYCJA dzięki @ypercube do pingowania na czacie.

Nawiasem mówiąc, być może nie chcesz w ogóle zrzucić całego adresu do jednej kolumny. Normalizacja może sugerować, że nie chcesz przechowywać @hotmail.com15 milionów razy, gdy znacznie chudszy FK int działałby dobrze i nie miałby dodatkowego obciążenia kolumny o zmiennej długości. Możesz także znormalizować nazwę użytkownika [email protected]i [email protected]udostępnić wspólną nazwę użytkownika - nie znają się, ale twoja baza danych nie dba o to.

Mówiłem o niektórych z tego tutaj:

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/

Wprowadza to jednak wyzwania dla powyższego limitu 254 znaków, ponieważ wydaje się, że nie ma zgody co do tego, co się stanie, gdy ważna domena 255 znaków zostanie połączona z prawidłową częścią lokalną 1-znakową. Powinno to zostać zaakceptowane przez większość serwerów na całym świecie, ale wydaje się, że narusza ten limit 254 znaków. Czy tworzysz więc Domainstabelę, która ma sztucznie niższe ograniczenie długości adresów e-mail, kiedy domena może być ponownie wykorzystana jako prawidłowy adres URL o długości 255 znaków?

Aaron Bertrand
źródło
Podoba mi się to podejście, ale co z wyjątkowością wiadomości e-mail? Jak to jest zarządzane?
Roberto Rizzi,
2
@RobertoRizzi Unikalne ograniczenie lub klucz podstawowy na połączeniu DomainID + LocalPart lub odwrotnie.
Aaron Bertrand
5

Istnieje kilka uwag dotyczących tej decyzji. Przede wszystkim należy wykorzystać bieżące i przyszłe prognozy niezbędnych ograniczeń, które dane będą musiały spełniać. Jest powód, dla którego nie chcesz ustawiać każdego typu danych kolumny ciągów, varchar(1024)gdy tylko przechowujesz ciąg, który nie powinien przekraczać 32 znaków (nacisk na słowo kluczowe powinno ).

Jeśli masz jakąś lukę w zabezpieczeniach, w której wszystkie e-maile są modyfikowane do 255 znaków, możesz potencjalnie mieć długi wpływ na wydajność podziału strony. Może się to wydawać niezwykłe i najprawdopodobniej tak jest, ale musisz dostosować swoje dane do wymagań biznesowych . Podobnie jak odwieczne ograniczenie w bazie danych vs. debata aplikacji, jestem głęboko przekonany, że ograniczenia typów danych i dopuszczalne wartości należy również egzekwować na poziomie danych.

Co prowadzi mnie do następnego punktu. Baza danych jest najprawdopodobniej tylko warstwą danych. Z czego korzysta warstwa aplikacji? Na przykład, jeśli masz aplikację, w której możesz wpisać tylko 80 znaków dla adresu e-mail, dlaczego chcesz, aby typ danych był większy? Firma musi odpowiedzieć na dwa pytania:

  1. Co to może być
  2. Co to powinno być?

Tylko wtedy otrzymasz swoją odpowiedź.

Czy varchar z definicji nie używa tyle pamięci, ile jest potrzebne do przechowywania danych?

Tak i nie. Będzie pewien rodzaj przesunięcia dla danych o zmiennej długości w celu zarejestrowania ich długości.

Thomas Stringer
źródło
3

RFC 5321 (aktualna specyfikacja SMTP, nieaktualne RFC2821) stwierdza:

Maksymalna łączna długość nazwy użytkownika lub innej części lokalnej wynosi 64 oktety. Maksymalna łączna długość nazwy domeny lub numeru wynosi 255 oktetów

Zatem znak 64 + 255 + @ oznacza VARCHAR (320). Prawdopodobnie nigdy tak bardzo nie będziesz potrzebować, ale na wszelki wypadek możesz mieć to bezpiecznie.

avakharia
źródło
4
Prawidłowy limit to 254. rfc-editor.org/errata_search.php?rfc=3696&eid=1690
Neil McGuigan
1

Każda odmiana VARCHAR zajmuje tylko tyle miejsca w bloku danych, ile potrzeba. Dodatkowe bajty do przechowywania długości są trywialne w porównaniu do miejsca, które zostałoby zmarnowane przy użyciu CHAR o stałej długości.

Ponieważ długość kolumny VARCHAR jest tak naprawdę „maksymalną długością”, powinna być ustawiona na większą niż maksymalna możliwa długość w każdych okolicznościach. Zostanie wykorzystana tylko tyle miejsca, ile potrzebuje każdy wiersz. Programy aplikacyjne powinny być zaprojektowane z przewijanymi polami lub cokolwiek innego, w oparciu o typowe wartości.

Projekt bazy danych jest jak fizyczny kawałek papieru, ponieważ określa twarde ograniczenia dotyczące rozmiaru. Strony papierowej nie można powiększyć. W tej analogii program aplikacyjny jest jak formularz wydrukowany na stronie. Wiele można zrobić, aby dostosować ilość danych, które możemy przechowywać w formularzu.

Chociaż polecenie zwiększenia rozmiaru VARCHAR może wydawać się proste i działać natychmiast na małej tabeli, wykonanie tego na tabeli z tysiącami lub więcej wierszy prawdopodobnie będzie wymagać pewnego rodzaju wyciszenia bazy danych podczas ponownego generowania wszystkich bloków danych i indeksów. Jednym ze sposobów jest skopiowanie wszystkiego do nowej tabeli z większymi kolumnami. Niezależnie od zastosowanej techniki jest to wielka sprawa. Dlatego należy rozważyć rozmiar kolumny VARCHAR w dużej mierze niezmienny po załadowaniu tabeli produkcyjnej.

DocSalvager
źródło
1

Jako komentarz do doskonałych odpowiedzi już tutaj:

Po pierwsze, jeśli utworzyłeś pole jako varchar(240)i chcesz później zmienić je na dłuższe pole, powiedzmy varchar(320), ta zmiana powinna być trywialną operacją na serwerze bazy danych - oczywiście w zależności od produktu bazy danych.

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

Po drugie, w zależności od średniego rozmiaru wiersza i rozmiaru strony użycie varchar(320)zamiast varchar(240)może nie zmienić liczby przydzielonych stron (miejsce na dysku faktycznie zajęte przez tabelę).

Po trzecie, ktoś powyżej mówił o sprawdzeniu poprawności adresu e-mail. Twierdzę, że istnieje tylko jeden pewny sposób na sprawdzenie adresu e-mail i wysłanie na niego wiadomości e-mail. :-)

Greenstone Walker
źródło
0

VARCHAR jest najlepszym typem danych do wykorzystania w przypadku adresów e-mail, ponieważ wiadomości e-mail różnią się znacznie pod względem długości. NVARCHAR jest również alternatywą, ale polecam go używać tylko wtedy, gdy adres e-mail zawiera rozszerzone znaki i pamiętaj, że wymaga on podwójnej ilości miejsca do przechowywania w porównaniu do VARCHAR.

W moim środowisku używamy varchar (70), ponieważ najdłuższe, na które się natknąłem, mają blisko 60-70 znaków, ale zależy to również od bazy klientów Twojej firmy. Ponadto, na marginesie, upewnij się, że masz jakieś sprawdzanie poprawności adresu e-mail na miejscu dla ważności adresów e-mail .. na przykład przy użyciu ograniczeń czeku lub CHARINDEX

Kin Shah
źródło
0

Korzystanie z SQL DOMAIN

Jeśli używasz serwera Enterprise Database, powinien istnieć sposób przechowywania adresu e-mail DOMAINo pewnym poziomie ważności. Domeny są określone w specyfikacji SQL

Domena to nazwany obiekt zdefiniowany przez użytkownika, który można określić jako alternatywę dla typu danych w niektórych miejscach, w których można określić typ danych. Domena składa się z typu danych, być może domyślnej opcji i zerowych lub więcej ograniczeń (domeny).

Na przykład, darmowy i open source PostgreSQL obsługuje to, z wyjątkiem wszelkich ograniczeń w implementacji specyfikacji, sama kolumna zawiera prawidłowy e-mail. Możesz na przykład ..

  • Utwórz niestandardowy DOMAINe-mail w specyfikacji HTML5.
  • Lub za pośrednictwem specyfikacji e-mail RFC822, RFC2822, RFC5322.
  • Utwórz niestandardowy, DOMAINktóry sprawdza serwer pod kątem rekordu MX w momencie sprawdzania.

Oceniam te opcje w tej odpowiedzi, która jest specyficzna dla PostgreSQL

Evan Carroll
źródło