Best practice per la lunghezza della colonna varchar SQL [chiusa]


288

Ogni volta che viene impostata una nuova tabella SQL o aggiunta una nuova varcharcolonna a una tabella esistente, mi chiedo una cosa: qual è il miglior valore per length.

Quindi, diciamo, hai una colonna chiamata namedi tipo varchar. Quindi, devi scegliere la lunghezza. Non riesco a pensare a un nome> 20 caratteri, ma non lo saprai mai. Ma invece di usare 20, arrotondo sempre al prossimo numero 2 ^ n. In questo caso, sceglierei 32 come lunghezza. Lo faccio, perché dal punto di vista dell'informatica, un numero 2 ^ n evenmi sembra più di altri numeri e sto solo supponendo che l'architettura sottostante possa gestire quei numeri leggermente meglio degli altri.

D'altra parte, ad esempio il server MSSQL, imposta il valore di lunghezza predefinito su 50, quando si sceglie di creare una colonna varchar. Questo mi fa pensare. Perché 50 è solo un numero casuale o basato sulla lunghezza media della colonna o cosa?

Potrebbe anche essere - o probabilmente lo è - che diverse implementazioni di server SQL (come MySQL, MSSQL, Postgres, ...) abbiano valori di lunghezza della colonna migliori diversi.

Risposte:


238

Nessun DBMS che conosco ha "ottimizzazioni" che consentano VARCHARa una 2^nlunghezza di funzionare meglio di una maxlunghezza che non è una potenza di 2.

Penso che le prime versioni di SQL Server abbiano effettivamente trattato una VARCHARlunghezza 255 diversa da una lunghezza maggiore. Non so se sia ancora così.

Per quasi tutti i DBMS, l'archiviazione effettiva richiesta è determinata solo dal numero di caratteri inseriti, non dalla maxlunghezza definita. Quindi, dal punto di vista dell'archiviazione (e molto probabilmente anche delle prestazioni), non fa alcuna differenza se si dichiara una colonna come VARCHAR(100)o VARCHAR(500).

Dovresti vedere la maxlunghezza fornita per una VARCHARcolonna come una sorta di vincolo (o regola aziendale) piuttosto che una cosa tecnico / fisica.

Per PostgreSQL la migliore configurazione è quella di utilizzare textsenza limiti di lunghezza e CHECK CONSTRAINTlimiti che limitano il numero di caratteri a qualunque cosa la tua azienda richieda.

Se tale requisito cambia, la modifica del vincolo di controllo è molto più rapida della modifica della tabella (poiché non è necessario riscrivere la tabella)

Lo stesso può essere applicato per Oracle e altri - in Oracle lo sarebbe VARCHAR(4000)invece che textperò.

Non so se esiste una differenza di archiviazione fisica tra VARCHAR(max)e, ad esempio, VARCHAR(500)in SQL Server. Ma a quanto pare c'è un impatto sulle prestazioni quando si utilizza varchar(max)rispetto a varchar(8000).

Vedi questo link (pubblicato da Erwin Brandstetter come commento)

Modifica 22-09-2013

Per quanto riguarda il commento di Bigown:

Nelle versioni Postgres precedenti alla 9.2 (che non era disponibile quando ho scritto la risposta iniziale) una modifica alla definizione della colonna ha riscritto l'intera tabella, vedi ad esempio qui . A partire da 9.2 questo non è più il caso e un rapido test ha confermato che aumentare le dimensioni della colonna per una tabella con 1,2 milioni di righe impiegava effettivamente solo 0,5 secondi.

Anche per Oracle questo sembra essere vero, a giudicare dal tempo impiegato per modificare la varcharcolonna di un grande tavolo . Ma non sono riuscito a trovare alcun riferimento per questo.

Per MySQL il manuale dice " Nella maggior parte dei casi, ALTER TABLEcrea una copia temporanea della tabella originale ". E i miei test confermano che: l'esecuzione di un ALTER TABLEsu una tabella con 1,2 milioni di righe (lo stesso del mio test con Postgres) per aumentare le dimensioni di una colonna ha richiesto 1,5 minuti. In MySQL tuttavia è possibile non utilizzare la "soluzione" per usare un vincolo di controllo per limitare il numero di caratteri in una colonna.

Per SQL Server non sono riuscito a trovare un'istruzione chiara su questo, ma il tempo di esecuzione per aumentare le dimensioni di una varcharcolonna (di nuovo la tabella da 1,2 milioni di righe dall'alto) indica che non viene eseguita alcuna riscrittura.

Modifica 24/01/2017

Sembra che mi sia (almeno in parte) sbagliato su SQL Server. Vedi questa risposta di Aaron Bertrand che mostra che la lunghezza dichiarata di a nvarcharo varcharcolonne fa un'enorme differenza per le prestazioni.


34
In realtà, c'è una differenza tra VARCHAR (255) e VARCHAR (500), anche se si inserisce 1 carattere all'interno di tale colonna. Il valore aggiunto alla fine della riga sarà un numero intero che memorizza la lunghezza effettiva dei dati memorizzati. Nel caso di VARCHAR (255) sarà 1 byte intero. Nel caso di VARCHAR (500) sarà di 2 byte. è una piccola differenza, ma bisogna esserne consapevoli. Non ho dati a portata di mano su come può influire sulle prestazioni, ma suppongo che sia così piccolo che non vale la pena ricercare.
NB

1
@NB: questo è ciò a cui mi riferivo per il valore "magico" 255 di SQL Server. Grazie per il chiarimento.
a_horse_with_no_name

4
@NB A quale RDBMS ti riferisci? Server SQL? C'è un effetto sulle prestazioni. [N] VARCHAR (max) si comporta leggermente più lentamente di [N] VARCHAR (n). Sono stato recentemente segnalato a questo sito . Lo stesso non è vero per PostgreSQL per quanto ne so.
Erwin Brandstetter,

@ErwinBrandstetter: grazie per il link. Sembra che varchar(max)probabilmente sia più simile a quello di OracleCLOB
a_horse_with_no_name

1
La modifica della lunghezza del varchar non riscrive la tabella. Controlla semplicemente la lunghezza del vincolo sull'intera tabella esattamente come CONTROLLA VINCERE. Se aumenti la lunghezza non c'è niente da fare, solo l'inserimento o gli aggiornamenti successivi accetteranno una lunghezza maggiore. Se riduci la lunghezza e tutte le righe superano il nuovo vincolo più piccolo, Pg non intraprende ulteriori azioni oltre a consentire a inserimenti o aggiornamenti successivi di scrivere solo la nuova lunghezza.
Maniero,

69

VARCHAR(255)e VARCHAR(2)occupa esattamente la stessa quantità di spazio sul disco! Quindi l'unico motivo per limitarlo è se hai una necessità specifica che sia più piccola. Altrimenti rendili tutti 255.

In particolare, quando si esegue l'ordinamento, le colonne più grandi occupano più spazio, quindi se ciò danneggia le prestazioni, è necessario preoccuparsi e ridurle. Ma se selezioni solo 1 riga da quella tabella, puoi semplicemente renderle tutte 255 e non importa.

Vedi: Quali sono le dimensioni varchar ottimali per MySQL?


7
Perché non farli tutti VARCHAR(MAX)? Lo spazio non è l'unica considerazione quando si modella un database. Il dominio che stai modellando dovrebbe guidare i tipi di dati e le dimensioni.
Oded,

6
@Oded VARCHAR(MAX)non è lo stesso di varchar(255)o varchar(65535)- varchar max è un tipo di tipo di textdati. E al tuo punto - se avesse saputo quale "dominio stava modellando" non avrebbe posto questa domanda. Chiaramente non sa quanto saranno grandi i suoi dati, e lo sto rassicurando sul fatto che renderli a grandezza naturale non fa male a nulla.
Ariel,

4
@Ariel: ci sono anche problemi e limitazioni sugli indici. Non puoi avere un (a,b,c,d)indice quando tutte e quattro le colonne sono VARCHAR(255).
ypercubeᵀᴹ

@ypercube Questo è vero, se le tue colonne hanno bisogno di un indice devi essere più attento con le dimensioni. Ma la maggior parte delle colonne non ha bisogno di un indice, quindi la maggior parte delle volte non devi preoccuparti.
Ariel,

Penso che se conosciamo il valore esatto preferisco usare char. Nel frattempo, se è ancora prevedibile, utilizzo varchar e mantengo 255 poiché si tratta di allocazione dinamica della memoria, quindi non ti preoccupare delle dimensioni che verranno prese
Faris Rayhan,

54

Ogni volta che imposto una nuova tabella SQL, mi sento allo stesso modo che 2 ^ n sia più "pari" ... ma per riassumere le risposte qui, non c'è alcun impatto significativo sullo spazio di archiviazione semplicemente definendo varchar (2 ^ n) o anche varchar (MAX).

Detto questo, dovresti comunque anticipare le potenziali implicazioni su archiviazione e prestazioni quando imposti un limite varchar () elevato. Ad esempio, supponiamo che crei una colonna varchar (MAX) per contenere le descrizioni dei prodotti con l'indicizzazione full-text. Se il 99% delle descrizioni sono lunghe solo 500 caratteri e all'improvviso ottieni qualcuno che sostituisce tali descrizioni con articoli di Wikipedia, potresti notare imprevisti significativi risultati di archiviazione e prestazioni.

Un'altra cosa da considerare da Bill Karwin :

C'è un possibile impatto sulle prestazioni: in MySQL, le tabelle temporanee e le tabelle MEMORY memorizzano una colonna VARCHAR come colonna a lunghezza fissa, riempita fino alla sua lunghezza massima. Se si progettano colonne VARCHAR molto più grandi della dimensione massima necessaria, si consumerà più memoria di quanto è necessario. Ciò influisce sull'efficienza della cache, sulla velocità di ordinamento, ecc.

Fondamentalmente, basta presentare ragionevoli vincoli aziendali ed errori su una dimensione leggermente più grande. Come sottolineato da @onedaywhen, i nomi di famiglia nel Regno Unito sono generalmente compresi tra 1 e 35 caratteri. Se decidi di renderlo varchar (64), non farai davvero del male a nulla ... a meno che tu non stia memorizzando il nome della famiglia di questo ragazzo che si dice abbia una lunghezza massima di 666 caratteri. In tal caso, forse varchar (1028) ha più senso.

E nel caso sia utile, ecco come potrebbe apparire varchar da 2 ^ 5 a 2 ^ 10 se riempito:

varchar(32)     Lorem ipsum dolor sit amet amet.

varchar(64)     Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie

varchar(128)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas

varchar(256)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt

varchar(512)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie

varchar(1024)   Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie
                dapibus leo lobortis eleifend. Vivamus vitae diam turpis. Vivamu
                nec tristique magna, vel tincidunt diam. Maecenas elementum semi
                quam. In ut est porttitor, sagittis nulla id, fermentum turpist.
                Curabitur pretium nibh a imperdiet cursus. Sed at vulputate este
                proin fermentum pretium justo, ac malesuada eros et Pellentesque
                vulputate hendrerit molestie. Aenean imperdiet a enim at finibus
                fusce ut ullamcorper risus, a cursus massa. Nunc non dapibus vel
                Lorem ipsum dolor sit amet, consectetur Praesent ut ultrices sit

31

Il valore migliore è quello giusto per i dati come definito nel dominio sottostante.

Per alcuni domini, VARCHAR(10)è giusto per l' Nameattributo, per altri domini VARCHAR(255)potrebbe essere la scelta migliore.


15

Aggiungendo alla risposta a_horse_with_no_name potresti trovare i seguenti di interesse ...

non fa alcuna differenza se si dichiara una colonna come VARCHAR (100) o VACHAR (500).

-- try to create a table with max varchar length
drop table if exists foo;
create table foo(name varchar(65535) not null)engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length - 2 bytes for the length
drop table if exists foo;
create table foo(name varchar(65533) not null)engine=innodb;

Executed Successfully

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65533))engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65532))engine=innodb;

Executed Successfully

Non dimenticare i byte di lunghezza e il byte nullable così:

name varchar(100) not null sarà 1 byte (lunghezza) + fino a 100 caratteri (latino1)

name varchar(500) not null sarà di 2 byte (lunghezza) + fino a 500 caratteri (latino1)

name varchar(65533) not null sarà di 2 byte (lunghezza) + fino a 65533 caratteri (latino1)

name varchar(65532) sarà di 2 byte (lunghezza) + fino a 65532 caratteri (latino1) + 1 byte null

Spero che questo ti aiuti :)


Stai usando MySQL e la domanda riguarda MSSQL
Bogdan Mart


3

Non ho verificato di recente, ma in passato so con Oracle che il driver JDBC avrebbe riservato un pezzo di memoria durante l'esecuzione della query per mantenere il set di risultati che tornava. La dimensione del blocco di memoria dipende dalle definizioni di colonna e dalla dimensione di recupero. Quindi la lunghezza delle colonne varchar2 influenza la quantità di memoria riservata. Ciò ha causato seri problemi di prestazioni per me anni fa, poiché usavamo sempre varchar2 (4000) (il massimo al momento) e la raccolta dei rifiuti era molto meno efficiente di quanto lo sia oggi.


-2

In un certo senso hai ragione, anche se qualcosa di meno di 2 ^ 8 caratteri verrà comunque registrato come byte di dati.

Se si considera il carattere di base che lascia qualcosa con un VARCHAR <255 come consumando la stessa quantità di spazio.

255 è una buona definizione di base a meno che non si desideri ridurre in modo particolare un input eccessivo.


" anche se qualcosa di meno di 2 ^ 8 caratteri verrà comunque registrato come byte di dati " - sbagliato. Il database memorizza solo tutti i caratteri forniti in un tipo VARCHAR. Nessuno spazio è "registrato", riservato o inizializzato quando si dichiara una colonna.
a_horse_with_no_name
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.