2013-05-05 12 views
8

Pretext, ho familiarità con le differenze semantiche tra un valore NULL e una stringa vuota.Stringa NULL o vuota più efficiente/naturale?

Ho una tabella MySQL in cui posso conservare un sacco di nomi di host con i loro indirizzi IP (come una stringa) e mi chiedo che cosa sarebbe sembrano essere più naturale (o efficiente stoccaggio-saggio) nel caso in cui un nome host non può essere risolto.

Un valore NULL o una stringa vuota (nel qual caso probabilmente dovrebbe essere un VARCHAR e non un CHAR)

avrei tendere ad un valore NULL ma desidero avere questo confermato o disconfermati.

+1

Questo è un po 'soggettivo, ma NULL trasporta il significato di "non applicabile" che sembra il più naturale qui. L'efficienza non dovrebbe essere un fattore. –

+0

@Jack Bene, l'efficienza è sempre un fattore;) – user2352129

+0

Gli hostname devono essere unici? Ti aspetti mai più indirizzi IP da risolvere sullo stesso hostname? –

risposta

4

In MyISAM MYSQL si salva un bit per riga non utilizzando NULL. Come indicato here:

Dichiarare le colonne NULL può ridurre il numero massimo di colonne consentito. Per le tabelle MyISAM, le colonne NULL richiedono uno spazio aggiuntivo nella riga per registrare se i loro valori sono NULL. Ogni colonna NULL richiede un bit in più, arrotondato al byte più vicino.

Date un'occhiata here così:

Inoltre, mentre un NULL sé non richiede spazio di memoria, riserve NDBCLUSTER 4 byte per riga se la definizione della tabella contiene tutte le colonne definite come NULL, fino a 32 colonne NULL. (Se una tabella MySQL Cluster è definita con più di 32 colonne NULL fino a 64 colonne NULL, quindi 8 byte per riga è riservata.)

Inoltre rende anche il lavoro del database veloce esso dichiarato here (tratto da stackoverflow - link @DavidWinterbottom non ha funzionato per me, ho aggiunto un sourse diversa)

e 'più difficile per MySQL per ottimizzare le query che fanno riferimento a coumns nullable, perché fanno sì che gli indici, statistiche di indice, e il confronto di valore più complicato. Una colonna nullable utilizza più spazio di archiviazione e richiede un'elaborazione speciale all'interno di MySQL. Quando viene indicizzata una colonna nullable, richiede un byte aggiuntivo per voce e può persino causare una dimensione fissa dell'inded (come un indice su una singola colonna di numeri interi) per essere convertita in una variabile in MyISAM.

Nella maggior parte dei casi, i valori non NULL si comportano più prevedibile quando combinato con COUNT() e l'altra funzione di aggregazione, ma è anche possibile vedere un NULL si comportano in base alle proprie esigenze.

Come si afferma here, non tutte le funzioni di gruppo (aggregati) ignorare NULL per esempio, COUNT() darebbe risultato diverso che COUNT(*) per una colonna contenente valori NULL.

D'altro canto, come altro punto, NULL riflette meglio il significato di voce - è un valore sconosciuto e se si desidera contare tutti gli host probabilmente si comporterà esattamente come fa COUNT().

+0

Il comportamento nulla non è mai stato un problema per me. Saresti così gentile da pubblicare un link al tuo argomento rispettabile sulla dimensione del bit del valore NULL? D'altra parte, "fa anche funzionare il database più velocemente" potrebbe utilizzare ulteriori dimostrazioni. (più grande non sempre significa più lento) – Sebas

+0

@Legat Vorrei davvero salvare questo bit?Presumo che sarebbe parte di una raccolta di bandiere interne, quindi sarebbe sempre lì e prendere spazio, solo non valutato nel caso in cui NULL non è consentito. – user2352129

+0

Grazie per aver menzionato la tua fonte. Vedo che parla chiaramente di MYISAM, il che significa che il motore di innodb è esentato. – Sebas

1

Oracle ha risolto il problema e lo ha interpretato allo stesso modo.

Mysql non lo fa, non lo giudico ma personalmente non mi piace, quindi uso NULL il più possibile per "standardizzare" il mio codice.

Inoltre, dal punto di vista del significato delle parole chiave, NULL è esattamente quello che vuoi perché significa "sconosciuto" nella semantica db. (correggimi se ho torto)

+1

Per quanto riguarda la semantica concordo, ecco perché preferirei tendenzialmente anche NULL, ma mi chiedo se una stringa vuota potrebbe avere un potenziale vantaggio in termini di prestazioni o dimensioni di archiviazione (IIRC NULL richiede un flag aggiuntivo). ...... Per quanto riguarda Oracle, non ero a conoscenza di questo e ho scoperto solo nel processo della mia ricerca, ma non sono davvero d'accordo con loro. Una stringa vuota non ha sempre necessariamente lo stesso significato di NULL e quindi non dovrebbe essere convertita automaticamente – user2352129

+0

sì, questo è giusto per la differenza di significato. Ma dopo un po 'ti rendi conto che è molto più chiaro evitare la doppia notazione. Ma questo è un punto di vista soggettivo, suppongo. – Sebas

+0

Dal punto di vista della performance o dello storage personalmente non preferiresti l'uno rispetto all'altro? – user2352129

0

Ti consiglio di utilizzare NULL, mentre il tipo di NULL è diverso dalla stringa. Ad esempio, è più semplice filtrare le righe con questo valore o rilevare il tipo di valore in quel campo e così via.

+1

Ma è anche possibile filtrare facilmente una stringa vuota. – user2352129

1

Prima: Considerare attentamente i diversi semantica di NULL e Vuoto-String.

  • La prima è meglio interpretato come qualcosa di simile a:
    C'è un valore valido per questo campo, ma tale valore non è ancora noto.
  • Il secondo indica sempre:
    Il valore valido per questo campo è noto ed è esattamente "".

Seconda: Riconoscere che l'indicizzazione e filtraggio funziona meglio e in modo più efficiente su Vuoto-String che su NULL, in modo da non utilizzare questi ultimi quando si ha realmente dire l'ex.

Terzo: Riconoscere che tutte le espressioni che utilizzano NULL sono sensibili alla non intuitività di tre valori logica a meno che il NULL viene religiosamente fusero per Vuoto-String (o qualche altro valore contestualmente validi) prima . In particolare, la legge del medio escluso non si applica più, quindi l'espressione A o ~ A non è più tautologicamente vera ogni volta che la valutazione di A richiede la valutazione di un termine NULL . Dimenticarlo può portare a bug molto sottili e difficili da localizzare.

Il non-uguale operatore espone con frequenza:

When A has the value NULL: 
    The expression A = 0 returns false; 
    The expression A <> 0 returns false; and 
    The expression A OR NOT A returns false! 

Aggiornamento:
Credo che l'essenza del mio punto è che non sono la stessa creatura, ma piuttosto molto diverse bestie. Ognuno ha il suo posto. Un secondo campo indirizzo deve essere sempre non nullo (a meno che non si intenda consentire l'immissione di indirizzi parziali o incompleti) e il suo valore predefinito dovrebbe sempre essere il valore valido e noto di Empty-String. NULL deve essere limitato ai casi in cui un valore valido e noto verrà fornito in un momento successivo e in effetti o segnalerà una sorta di errore di convalida che deve essere risolto.

Da OP seguito:

Una riga non verrà aggiornata. All'inserimento c'è un indirizzo IP o non ce n'è (perché non è stato possibile risolverlo).

Risposta:

Poi mi consiglia di utilizzare Vuoto-String come predefinito, e rendere il campo non nullo. Utilizzare solo NULL quando è necessario, in quanto ha sottili svantaggi.

+0

Ti ho preso fino all'ultimo paragrafo. Nel mio caso si potrebbero discutere entrambe le soluzioni (NULL, l'host non può essere risolto ed è sconosciuto - "", l'host non può essere risolto ma è stato effettuato un tentativo in modo che il risultato sia vuoto). ........ Dalla tua risposta non ho capito quale soluzione avresti optato, potresti approfondire questo? – user2352129

+0

@ user2352129: Credo che l'essenza del mio punto sia che sono ** NON ** la stessa creatura, ma piuttosto bestie molto diverse. Ognuno ha il suo posto. Un secondo campo indirizzo deve essere sempre non nullo (a meno che non si invii _intend_ per consentire l'immissione di indirizzi parziali o incompleti) e il valore predefinito dovrebbe sempre essere il valore _valid e known_ di ** Empty-String **. ** NULL ** dovrebbe essere limitato ai casi in cui un valore _valid e known_ verrà fornito in seguito e in effetti o segnalerà una sorta di errore di convalida che deve essere risolto. ... –

+0

@ user2352129: Nel tuo esempio non riesco a vedere dove hai definito la semantica di questo campo sufficientemente per fare una determinazione. Sospetto che dovresti rendere nulla il campo, ma definirlo come predefinito ** Empty-Sting **. In questo modo l'applicazione può assegnare ** NULL ** esplicitamente a "Esiste, ma devo trovare il valore"; ma il valore predefinito di ** Empty-String ** che significa "Non ce n'è uno" viene inserito nella creazione del record iniziale. È la semantica corretta della tua fila di tavoli? –