it-swarm.it

Implicazioni prestazionali delle dimensioni MySQL VARCHAR

C'è una differenza di prestazioni in MySQL tra le dimensioni di varchar? Ad esempio, varchar(25) e varchar(64000). In caso contrario, c'è un motivo per non dichiarare tutti i varchar con la dimensione massima solo per assicurarsi di non rimanere senza spazio?

46
BenV

È necessario realizzare i compromessi dell'utilizzo di CHAR vs VARCHAR

Con i campi CHAR, ciò che assegni è esattamente quello che ottieni. Ad esempio, CHAR (15) alloca e memorizza 15 byte, indipendentemente dal carattere inserito nel campo. La manipolazione delle stringhe è semplice e diretta poiché la dimensione del campo dati è totalmente prevedibile.

Con i campi VARCHAR, ottieni una storia completamente diversa. Ad esempio VARCHAR (15) alloca effettivamente in modo dinamico fino a 16 byte, fino a 15 per i dati e, almeno, 1 byte aggiuntivo per memorizzare la lunghezza dei dati. Se hai la stringa 'ciao' da memorizzare che richiederà 6 byte, non 5. La manipolazione della stringa deve sempre eseguire una qualche forma di controllo della lunghezza in tutti i casi.

Il compromesso è più evidente quando fai due cose:
1. Memorizzare milioni o miliardi di righe
2. Colonne di indicizzazione che sono CHAR o VARCHAR

TRADEOFF # 1

Ovviamente, VARCHAR ha il vantaggio poiché i dati a lunghezza variabile produrrebbero file più piccole e, quindi, file fisici più piccoli.

TRADEOFF # 2

Poiché i campi CHAR richiedono una minore manipolazione delle stringhe a causa della larghezza fissa dei campi, le ricerche dell'indice rispetto al campo CHAR sono in media il 20% più veloci rispetto a quelle dei campi VARCHAR. Questa non è alcuna congettura da parte mia. Il libro MySQL Database Design and Tuning ha eseguito qualcosa di meraviglioso su una tabella MyISAM per dimostrarlo. L'esempio nel libro ha fatto qualcosa di simile al seguente:

ALTER TABLE tblname ROW_FORMAT=FIXED;

Questa direttiva impone ai VARCHAR di comportarsi come CHAR. L'ho fatto nel mio precedente lavoro nel 2007, ho preso un tavolo da 300 GB e accelerato la ricerca dell'indice del 20%, senza cambiare nient'altro. Ha funzionato come pubblicato. Tuttavia, ha prodotto un tavolo di dimensioni quasi doppie, ma questo risale semplicemente al compromesso n. 1.

È possibile analizzare i dati archiviati per vedere cosa consiglia MySQL per la definizione di colonna. Basta eseguire quanto segue su qualsiasi tabella:

SELECT * FROM tblname PROCEDURE ANALYSE();

Ciò attraverserà l'intera tabella e raccomanderà le definizioni di colonna per ogni colonna in base ai dati in essa contenuti, ai valori minimi dei campi, ai valori massimi dei campi e così via. A volte, devi solo usare il buon senso con la pianificazione di CHAR vs VARCHAR. Ecco un buon esempio:

Se si memorizzano gli indirizzi IP, la maschera per tale colonna è al massimo di 15 caratteri (xxx.xxx.xxx.xxx). Vorrei saltare a CHAR (15) in un batter d'occhio perché la lunghezza degli indirizzi IP non varierà molto e la complessità della manipolazione delle stringhe controllata da un byte aggiuntivo. È ancora possibile eseguire una PROCEDURA ANALISI () su tale colonna. Potrebbe anche raccomandare VARCHAR. In questo caso, i miei soldi sarebbero ancora su CHAR su VARCHAR.

I problemi CHAR vs VARCHAR possono essere risolti solo attraverso un'adeguata pianificazione. Da un grande potere derivano grandi responsabilità (cliché ma vero)

30
RolandoMySQLDBA

La risposta a questo è in realtà piuttosto complessa. La versione breve: c'è una differenza.

  1. Quando si creano tabelle temporanee per filtrare i risultati (ad esempio GROUP BY dichiarazioni), verrà assegnata l'intera lunghezza.

  2. Il protocollo wire (invio di righe al client) assegnerà probabilmente la lunghezza maggiore.

  3. Il motore di archiviazione potrebbe/potrebbe non implementare un varchar adeguato.

Per (2) ammetto che il protocollo wire non è qualcosa che conosco intimamente, ma il consiglio generale qui è provare e applicare almeno un minimo sforzo per indovinare la lunghezza.

13
Morgan Tocker

La maggior parte delle risposte in questa discussione sono cinque otto anni, scritto prima di InnoDB e utf8 erano valori predefiniti. Quindi, lasciami ricominciare ...

Quando una query necessita di una tabella temporanea interna, tenta di utilizzare una tabella MEMORY. Ma MEMORY non può essere usato se

  • TEXT/BLOB colonne recuperate, anche TINYTEXT.
  • VARCHAR più grande di un certo importo, probabilmente 512 nella versione corrente.

Inoltre, si noti che VARCHARs vengono trasformati in CHARs. (8.0 lo modifica.) Quindi, VARCHAR(255) con un CHARACTER SET utf8 Si espande a 765 byte, indipendentemente da ciò che è nella colonna. Quindi, questo potrebbe essere attivato:

  • Se la tabella MEMORY diventa più grande di max_heap_table_sizeotmp_table_size, Verrà convertita in MyISAM e potenzialmente versata su disco.

Pertanto, VARCHAR(25) ha maggiori probabilità di rimanere MEMORY, quindi essere più veloce. (255) Non è buono e (64000) Non è buono.

(In futuro, le tabelle temporanee saranno probabilmente InnoDB e parte di questa risposta dovrà essere rivista.)

11
Rick James

Una colonna varchar di quelle dimensioni rende più probabile che le query sull'intera tabella utilizzino le tabelle temporanee. Secondo il libro MySQL ad alte prestazioni. Quando l'ottimizzatore tenta di vedere se è in grado di eseguire questa query in memoria o se necessita di una tabella temporanea, esamina la dimensione della riga in base alla definizione della tabella, ovvero, per velocità, non prova a vedere la quantità di 64 KB di caratteri stai effettivamente usando. Questo è il motivo per cui gli autori raccomandano di non estendere quella definizione ben oltre i possibili valori effettivi che andrebbero nella colonna. Ovviamente, se ti imposti per ulteriori query andando nelle tabelle temporanee (anche se la dimensione effettiva dei dati potrebbe rientrare nella RAM) ora hai subito penalità I/O che avresti potuto evitare.

6
TechieGurl

Comprendo che i campi più piccoli possono essere inclusi direttamente nell'indice, mentre quelli più lunghi non possono essere inclusi. A causa di tale limitazione, se si desidera che le stringhe siano indicizzabili, direi di mantenerle più brevi. Altrimenti, no, essendo come sono entrambi varchar, le operazioni come l'ordinamento o il confronto funzioneranno in modo simile, indipendentemente dal fatto che i campi siano 25 o MAX.

5
jcolebrand

assicurarsi di non rimanere a corto di spazio

Questa frase implica che si pone la domanda perché non si è sicuri dei dati che verranno archiviati nel database. Se questo è vero, sarai ben servito a scoprirlo il prima possibile, perché ne avrai bisogno per pianificare la capacità. Ad esempio, se si ottengono elementi di dati con 7000 caratteri, è necessario sapere perché ciò avrebbe implicazioni in termini di prestazioni su qualsiasi DBMS.

Detto questo, preferisco avere dimensioni delle colonne correlate ai contenuti previsti. Ad esempio, è improbabile che un numero di telefono sia più lungo di 50 caratteri, anche se includi un prefisso internazionale e un interno. Allo stesso modo, un codice postale o postale avrà probabilmente 20 caratteri o meno.

3
Larry Coleman