In quale tipo di dati devo memorizzare un indirizzo e-mail nel database?


44

Comprendo che un indirizzo e-mail di 254 caratteri è valido, ma le implementazioni che ho studiato tendono a utilizzare un varchar (60) in varchar (80) o equivalente. Ad esempio: questa raccomandazione di SQL Server utilizza varchar (80) o questo esempio Oracle

C'è un motivo per non usare il massimo di 254 caratteri al massimo? Un varchar per definizione non utilizza solo la quantità di memoria necessaria per conservare i dati?

Ci sono implicazioni / compromessi significativi sulle prestazioni che fanno sì che così tante implementazioni utilizzino meno dei 254 caratteri possibili?

Risposte:


45

L'ho sempre usato VARCHAR(320). Ecco perché. Lo standard impone le seguenti limitazioni:

  • 64 caratteri per la "parte locale" (nome utente).
  • 1 carattere per il @simbolo.
  • 255 caratteri per il nome del dominio.

Ora, alcune persone diranno che è necessario supportare di più. Alcune persone diranno anche che è necessario supportare Unicode per i nomi di dominio (il che significa che è necessario passare a NVARCHAR). Mentre lo standard potrebbe cambiare nel frattempo (è da un po 'che non ho skin nel gioco), sono abbastanza fiducioso che in questo momento la maggior parte dei server nel mondo non accetteranno indirizzi e-mail Unicode e sono sicuro molti server avranno problemi a creare e / o accettare indirizzi con> 320 caratteri.

Detto questo, puoi prepararti al peggio ora, se lo desideri (e se stai utilizzando la compressione dei dati in SQL Server 2008 R2 o superiore, beneficerai della compressione Unicode, il che significa che pagherai solo la penalità di 2 byte per i caratteri che hanno effettivamente bisogno esso). In questo modo puoi allargare la tua colonna quanto vuoi e puoi permettere alle persone di riempire qualsiasi spazzatura troppo lunga lì dentro che vogliono - non riceveranno un'e-mail se ti danno spazzatura proprio come non vogliono ricevere un'e-mail se l'inserimento non riesce. Il problema è se lasci entrare spazzatura non valida, tuavere a che fare con esso. E non importa quale sia la tua dimensione: se qualcuno proverà a riempire 400 caratteri in una colonna di 320 caratteri, qualcuno proverà a riempire 1025 caratteri in una colonna di 1024 caratteri. Non vi è alcun motivo per cui una persona sensibile dovrebbe avere un indirizzo e-mail> 320 caratteri a meno che non lo utilizzino per testare esplicitamente i confini del sistema.

Ma smetti di chiedere opinioni su questo - e smetti di guardare altre implementazioni come guida (succede solo che in questo caso quelle a cui hai fatto riferimento non si sono preoccupate di fare i compiti e hanno semplicemente selezionato i numeri dai loro, beh, sai) . Hai accesso diretto allo standard : assicurati di consultare la versione più recente, di supportarla come minimo e di rimanere in cima allo standard in modo da poterti adattare alle modifiche delle specifiche.


MODIFICA grazie a @ypercube per il ping in chat.

A parte questo, forse non vuoi scaricare l'intero indirizzo in una singola colonna in primo luogo. La normalizzazione potrebbe suggerire che non si desidera archiviare @hotmail.com15 milioni di volte in cui un FK molto più magro funzionerebbe perfettamente e non avrebbe l'overhead aggiuntivo di colonne di lunghezza variabile. Si potrebbe anche normalizzare il nome utente, come john.smith@hotmail.come john.smith@gmail.comcondividono un nome utente comune - non sanno l'un l'altro, ma il database non si preoccupa di questo.

Ne ho parlato in parte qui:

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/

Ciò introduce tuttavia delle sfide al limite di 254 caratteri sopra, poiché non sembra esserci consenso su ciò che accade quando un dominio valido di 255 caratteri viene combinato con una parte locale valida di 1 carattere. Questo dovrebbe essere accettato dalla maggior parte dei server in tutto il mondo, ma sembra violare questo limite di 254 caratteri. Quindi crei una Domainstabella che ha una limitazione artificialmente inferiore sulla lunghezza per gli indirizzi di posta elettronica, quando il dominio può essere riutilizzato come un URL valido di 255 caratteri?


Mi piace questo approccio, ma per quanto riguarda l'unicità della posta elettronica? Come viene gestito?
Roberto Rizzi,

2
@RobertoRizzi Un vincolo univoco o chiave primaria sulla combinazione di DomainID + LocalPart o viceversa.
Aaron Bertrand

5

Ci sono alcune considerazioni su questa decisione. Innanzitutto è utilizzare le previsioni attuali e future delle limitazioni necessarie a cui i dati dovranno conformarsi. C'è un motivo per cui non vuoi impostare tutti i tipi di dati della colonna stringa varchar(1024)quando stai semplicemente memorizzando una stringa che non deve superare i 32 caratteri (enfasi sulla parola chiave should ).

Se hai una sorta di vulnerabilità in cui le e-mail sono tutte modificate per diventare 255 caratteri, potresti potenzialmente avere un impatto a lungo sulle prestazioni delle suddivisioni di pagina. Questo può sembrare fuori dal comune, e molto probabilmente lo è, ma è necessario dimensionare i dati in base alle esigenze aziendali . Proprio come il vincolo secolare del database rispetto al dibattito sull'applicazione, sono fermamente convinto che le limitazioni dei tipi di dati e i valori consentiti dovrebbero essere applicati anche a livello di dati.

Il che mi porta al prossimo punto. Il database è molto probabilmente solo il livello dati. Cosa utilizza il livello applicazione? Ad esempio, se si dispone di un'applicazione in cui è possibile inserire solo 80 caratteri per un indirizzo e-mail, perché il tipo di dati dovrebbe essere più grande? Le aziende devono rispondere a due domande:

  1. Cosa può essere?
  2. Che cosa dovrebbe essere?

Solo allora avrai la tua risposta.

Un varchar per definizione non utilizza solo la quantità di memoria necessaria per conservare i dati?

Sì e no. Ci sarà una sorta di offset per i dati a lunghezza variabile per registrarne la lunghezza.


3

RFC 5321 (l'attuale specifica SMTP, viola RFC2821) afferma:

La lunghezza totale massima di un nome utente o altra parte locale è 64 ottetti. La lunghezza totale massima di un nome o numero di dominio è 255 ottetti

Quindi 64 + 255 + @ sign implica VARCHAR (320). Probabilmente non avrai mai bisogno di così tanto, ma è sicuro averlo, per ogni evenienza.



1

Qualsiasi variazione di VARCHAR utilizza solo lo spazio nel blocco dati necessario. I byte aggiuntivi per la memorizzazione della lunghezza sono banali rispetto allo spazio che verrebbe sprecato usando un CHAR di lunghezza fissa.

Poiché una lunghezza di colonna VARCHAR è in realtà una "lunghezza massima", deve essere impostata su una lunghezza maggiore della lunghezza massima possibile in qualsiasi circostanza. Verrà utilizzato solo lo spazio necessario per ogni riga. I programmi applicativi dovrebbero quindi essere progettati con campi di scorrimento o qualsiasi cosa abbia senso in base a valori tipici.

Un progetto di database è come un pezzo di carta fisico in quanto stabilisce i limiti rigidi per quanto riguarda le dimensioni. Una pagina di carta non può essere ingrandita. In questa analogia, il programma applicativo è come un modulo stampato sulla pagina. È possibile fare molto per regolare la quantità di dati che possiamo contenere nel modulo.

Sebbene il comando per aumentare una dimensione VARCHAR possa sembrare semplice ed eseguirsi istantaneamente su una piccola tabella, farlo su una tabella con migliaia di righe o più richiederà probabilmente un qualche tipo di sospensione del database durante la rigenerazione di tutti i blocchi di dati e indici. Un modo è copiare tutto in una nuova tabella con le colonne più grandi. Qualunque sia la tecnica utilizzata, è un grosso problema. Pertanto, una volta caricata una tabella di produzione, è necessario considerare la dimensione della colonna VARCHAR in gran parte immutabile.


1

Come commento alle eccellenti risposte già qui:

Innanzitutto, se hai creato il campo come varchar(240)e desideri successivamente modificarlo in un campo più lungo, ad esempio varchar(320), questa modifica dovrebbe essere un'operazione banale sul server di database, a seconda, ovviamente, del tuo prodotto di database.

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

In secondo luogo, a seconda della dimensione media della riga e della dimensione della pagina, l'utilizzo al varchar(320)posto di varchar(240)potrebbe non modificare il numero di pagine allocate (lo spazio su disco effettivamente occupato dalla tabella).

Terzo, qualcuno sopra ha parlato della convalida di un indirizzo e-mail. Sostengo che esiste un solo modo sicuro per convalidare un indirizzo e-mail e che è quello di inviargli un'e-mail. :-)


0

VARCHAR è il miglior tipo di dati da utilizzare per gli indirizzi e-mail poiché le e-mail variano molto in base alla lunghezza. Anche NVARCHAR è un'alternativa, ma lo consiglio di usarlo solo se l'indirizzo e-mail contiene caratteri estesi e tenere presente che richiede una doppia quantità di spazio di archiviazione rispetto a VARCHAR.

Nel mio ambiente, utilizziamo varchar (70) poiché i più lunghi che ho incontrato sono lunghi da 60 a 70 caratteri, ma dipendono anche dalla base di clienti della vostra azienda. Inoltre, come nota a margine, assicurati di avere un controllo di convalida e-mail sul posto per la validità degli indirizzi e-mail .. come usare i vincoli di controllo o CHARINDEX


0

Utilizzando SQL DOMAIN

Se si utilizza un server di database aziendale, dovrebbe esserci un modo per memorizzare un indirizzo e-mail DOMAINcon un livello di validità. I domini sono specificati nella specifica SQL

Un dominio è un oggetto definito dall'utente definito che può essere specificato in alternativa a un tipo di dati in determinati luoghi in cui è possibile specificare un tipo di dati. Un dominio è costituito da un tipo di dati, possibilmente un'opzione predefinita e zero o più vincoli (dominio).

Ad esempio, PostgreSQL gratuito e open source lo supporta, salvo eventuali limitazioni nell'implementazione delle specifiche, la colonna stessa contiene un messaggio di posta elettronica valido. Puoi ad esempio ..

  • Crea una personalizzazione DOMAINoltre la specifica HTML5 dell'email.
  • Oppure, tramite le specifiche di posta elettronica RFC822, RFC2822, RFC5322.
  • Crea un'abitudine DOMAINche controlla il server per un record MX al momento del controllo.

Valuto queste opzioni in questa risposta che è specifica di PostgreSQL

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.