Un valore di colonna vuoto occupa lo stesso spazio di archiviazione di un valore di colonna riempito?


15

Ho una tabella con 2 colonne. Il tipo di entrambe le colonne è impostato suvarchar(38) . Se creo una riga con un valore vuoto per una delle colonne, occuperà lo stesso spazio di archiviazione come se il valore non fosse vuoto?

In altre parole, MySQL riserverà spazio di archiviazione per la colonna (a seconda del tipo) quando viene creata una riga?

Risposte:


11

Dalla struttura della riga fisica di Innodb, punto elenco 7 in REDUNDANT ROW_FORMAT

Un valore NULL SQL riserva uno o due byte nella directory dei record. Oltre a ciò, un valore NULL SQL riserva zero byte nella parte di dati del record se memorizzato in una colonna di lunghezza variabile . In una colonna a lunghezza fissa, si riserva la lunghezza fissa della colonna nella parte dati del record. La prenotazione dello spazio fisso per i valori NULL consente di eseguire un aggiornamento della colonna da NULL a un valore non NULL senza causare la frammentazione della pagina dell'indice.

Dalla struttura della riga fisica di Innodb, punto elenco 2 in COMPACT ROW_FORMAT

La parte a lunghezza variabile dell'intestazione del record contiene un vettore di bit per indicare le colonne NULL. Se il numero di colonne nell'indice che può essere NULL è N, il vettore di bit occupa byte SOFFITTO (N / 8) . (Ad esempio, se esistono da 9 a 15 colonne che possono essere NULL, il vettore di bit utilizza due byte. Le colonne NULL non occupano spazio diverso dal bit in questo vettore . La parte a lunghezza variabile dell'intestazione contiene anche le lunghezze delle colonne a lunghezza variabile. Ogni lunghezza richiede uno o due byte, a seconda della lunghezza massima della colonna. Se tutte le colonne dell'indice NON sono NULL e hanno una lunghezza fissa, l'intestazione del record non ha una parte a lunghezza variabile.

Sulla base di questi punti elenco, ecco cosa occupa un NULLvalore per l'archiviazione di una colonna

  • lunghezza variabile: un valore NULL non occupa spazio nella riga stessa
  • lunghezza fissa: occupa lo spazio riservato

Ora, devi decidere tra usare CHAR e VARCHAR a causa di ciò che il primo punto ha messo in evidenza

La prenotazione dello spazio fisso per i valori NULL consente di eseguire un aggiornamento della colonna da NULL a un valore non NULL senza causare la frammentazione della pagina dell'indice

Ciò impedirà l'introduzione di qualsiasi frammentazione di una riga che scende lungo la strada una volta memorizzati i dati non NULL. Questo è qualcosa di cui ho già discusso in merito a MyISAM: vedi il mio vecchio post Qual è l'impatto sulle prestazioni dell'utilizzo di CHAR vs VARCHAR su un campo di dimensioni fisse? .


Ciao Rolando, c'era un altro elemento che ho dimenticato di menzionare, la differenza nell'allocazione di memoria tra una dichiarazione di tipo varchar (5) e varchar (100). O davvero la penalità sostenuta dall'allocazione eccessiva.
Craig Efrein,

@CraigEfrein Dovresti assolutamente aggiungere l'allocazione di memoria alla tua risposta. (A proposito ho già votato per la tua risposta)
RolandoMySQLDBA il

1
La penalità per l'allocazione eccessiva si verifica quando si dispone di un complesso SELECTche deve creare una tabella temporanea. Se possibile, userà MEMORYe convertirà VARCHARin CHARper la tabella tmp. Ora VARCHAR(100)richiede un numero fisso di 100 (o 300) byte, quindi può rallentare la query.
Rick James,

@RolandoMySQLDBA, il comportamento spiegato nella risposta è applicabile per i formati di riga Mysql 5.7 DYNAMIC e COMPACT.
Dinesh Kumar,

@DineshKumar Questi paragrafi sono ancora nei documenti 5.7 / 8.0. Fare riferimento a dev.mysql.com/doc/refman/5.7/en/innodb-row-format-dynamic.html per DYNAMIC.
RolandoMySQLDBA

8

Indipendentemente dalla lunghezza definita per la colonna varchar, lo spazio di archiviazione utilizzato da una colonna vuota sarà lo stesso.

I tipi CHAR e VARCHAR

inserisci qui la descrizione dell'immagine

Questo riguarda solo lo spazio utilizzato dalla colonna varchar e non considera lo spazio di archiviazione totale utilizzato dalla riga, i suoi indici, le chiavi primarie e altre colonne.

Come menziona ypercube nel suo commento, ci sono ulteriori considerazioni per l'archiviazione di righe nel suo insieme quando è presente almeno una colonna nullable.

Struttura della riga fisica Innodb

La parte a lunghezza variabile dell'intestazione del record contiene un vettore di bit per indicare le colonne NULL. Se esistono da 9 a 15 colonne che possono essere NULL, il vettore di bit utilizza due byte.)

...

La parte a lunghezza variabile dell'intestazione contiene anche le lunghezze delle colonne a lunghezza variabile. Ogni lunghezza richiede uno o due byte, a seconda della lunghezza massima della colonna. Se tutte le colonne dell'indice NON sono NULL e hanno una lunghezza fissa, l'intestazione del record non ha una parte a lunghezza variabile

E sì, lo spazio di archiviazione utilizzato cambia in base al tipo scelto, è fisso o variabile, le regole di confronto e altri fattori come il motore.

MySQL fornisce consigli sull'ottimizzazione della memorizzazione dei dati qui: Ottimizzazione della dimensione dei dati

Aggiornare

Un'ulteriore considerazione con varchar e questa è memoria. In MySQL è importante limitare il più possibile le dimensioni di una colonna di lunghezza variabile. Anche se la colonna è variabile e lo spazio di archiviazione utilizzato è variabile, MySQL alloca la memoria in blocchi fissi per memorizzare i valori. Ad esempio varchar (200) utilizzerà più memoria di varchar (5). Questo non è un problema di spazio di archiviazione, ma comunque qualcosa da considerare quando si definiscono le colonne.


I numeri qui sopra assumono CHARACTER SETlatino1 o ascii. Per utf8, lo spazio di archiviazione richiesto CHAR(4)è 12.
Rick James,
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.