Domanda

Mi rendo conto che CHAR è consigliato se tutti i miei valori sono a larghezza fissa.Ma allora?Perché non scegliere semplicemente VARCHAR per tutti i campi di testo solo per sicurezza.

È stato utile?

Soluzione

Generalmente scegli CAR se tutte le righe avranno vicino a stessa lunghezza.Scegliere VARCHAR quando il la lunghezza varia in modo significativo.CHAR potrebbe anche essere un po' più veloce perché tutte le righe hanno la stessa lunghezza.

Varia in base all'implementazione del DB, ma generalmente VARCHAR utilizza uno o due byte in più di spazio di archiviazione (per lunghezza o terminazione) oltre ai dati effettivi.Quindi (supponendo che tu stia utilizzando un set di caratteri da un byte) memorizzando la parola "FooBar"

  • CHAR(6) = 6 byte (nessun sovraccarico)
  • VARCHAR(10) = 8 byte (2 byte di sovraccarico)
  • CHAR(10) = 10 byte (4 byte di sovraccarico)

La linea di fondo è CAR può essere Più veloce e altro ancora efficiente in termini di spazio per dati di lunghezza relativamente identica (con una differenza di lunghezza entro due caratteri).

Nota:Microsoft SQL ha 2 byte di sovraccarico per un VARCHAR.Questo può variare da DB a DB, ma generalmente è necessario almeno 1 byte di sovraccarico per indicare la lunghezza o l'EOL su un VARCHAR.

Come sottolineato da Gaven nei commenti, se si utilizza un set di caratteri multibyte a lunghezza variabile come UTF8, CHAR memorizza il numero massimo di byte necessari per memorizzare il numero di caratteri.Pertanto, se UTF8 necessita di un massimo di 3 byte per memorizzare un carattere, allora CHAR(6) verrà fissato a 18 byte, anche se si memorizzano solo caratteri latin1.Quindi in questo caso VARCHAR diventa una scelta molto migliore.

Altri suggerimenti

Se lavori con me e lavori con Oracle, probabilmente ti farei usare varchar in quasi ogni circostanza.Il presupposto che char utilizza meno potenza di elaborazione rispetto a varchar potrebbe essere vero...per ora...ma i motori di database migliorano nel tempo e questa sorta di regola generale ha la possibilità di diventare un futuro "mito".

Un'altra cosa:Non ho mai visto un problema di prestazioni perché qualcuno ha deciso di seguirlo varchar.Utilizzerai molto meglio il tuo tempo scrivendo un buon codice (meno chiamate al database) e SQL efficiente (come funzionano gli indici, come prende decisioni l'ottimizzatore, perché è exists più veloce di in Generalmente...).

Pensiero finale:Ho riscontrato tutti i tipi di problemi con l'uso di CHAR, persone che cercano '' quando dovrebbero cercare '', o persone che cercano 'FOO' quando dovrebbero cercare 'FOO (un mucchio di spazi qui)', o persone che non tagliano gli spazi finali, o bug con Powerbuilder aggiungendo fino a 2000 spazi al valore restituito da una procedura Oracle.

Oltre ai vantaggi in termini di prestazioni, CHAR può essere utilizzato per indicare che tutti i valori Dovrebbe avere la stessa lunghezza, ad esempio una colonna per gli Stati Unitiabbreviazioni di stato.

Char è un po' più veloce, quindi se hai una colonna che SAI avrà una certa lunghezza, usa char.Ad esempio, memorizzando (M)ale/(F)emale/(U)nknown per il sesso o 2 caratteri per uno stato degli Stati Uniti.

NChar o Char hanno prestazioni migliori delle loro alternative var?

Ottima domanda.La risposta semplice è sì in determinate situazioni.Vediamo se questo può essere spiegato.

Ovviamente sappiamo tutti che se creo una tabella con una colonna varchar(255) (chiamiamo questa colonna myColumn) e inserisco un milione di righe ma inserisco solo pochi caratteri in myColumn per ogni riga, la tabella sarà molto più piccola (nel complesso numero di pagine di dati necessarie al motore di archiviazione) rispetto a quando avessi creato myColumn come char(255).Ogni volta che eseguo un'operazione (DML) su quella tabella e richiedo molte righe, sarà più veloce quando myColumn è varchar perché non devo farlo mossa attorno a tutti quegli spazi "extra" alla fine.Sposta, come quando SQL Server esegue ordinamenti interni come durante un'operazione distinta o di unione o se sceglie un'unione durante il suo piano di query, ecc.Lo spostamento potrebbe anche significare il tempo necessario per trasferire i dati dal server al mio PC locale o a un altro computer o ovunque verranno consumati.

Ma c'è qualche sovraccarico nell'uso di varchar.SQL Server deve utilizzare un indicatore di due byte (overhead) per, su ogni riga, sapere quanti byte contiene myColumn di quella particolare riga.Non sono i 2 byte in più a presentare il problema, è la necessità di "decodificare" la lunghezza dei dati in myColumn su ogni riga.

Nella mia esperienza ha più senso utilizzare char anziché varchar sulle colonne a cui verranno unite le query.Ad esempio la chiave primaria di una tabella o qualche altra colonna che verrà indicizzata.CustomerNumber su una tabella demografica o CodeID su una tabella di decodifica o forse OrderNumber su una tabella degli ordini.Utilizzando char, il motore di query può eseguire l'unione più rapidamente perché può eseguire l'aritmetica diretta dei puntatori (in modo deterministico) anziché dover spostare i puntatori di una quantità variabile di byte mentre legge le pagine.So che potrei averti perso con quell'ultima frase.I join in SQL Server si basano sull'idea di "predicati". Un predicato è una condizione.Ad esempio myColumn = 1 o OrderNumber < 500.

Pertanto, se SQL Server sta eseguendo un'istruzione DML e i predicati o le "chiavi" a cui si unisce hanno una lunghezza fissa (caratteri), il motore delle query non deve fare molto lavoro per far corrispondere le righe di una tabella alle righe di un altro tavolo.Non dovrà scoprire quanto tempo sono i dati nella riga e poi percorrere la stringa per trovare la fine.Tutto ciò richiede tempo.

Ora tieni presente che questo può facilmente essere implementato male.Ho visto caratteri utilizzati per i campi chiave primari nei sistemi online.La larghezza deve essere mantenuta piccola, ad es.char(15) o qualcosa di ragionevole.E funziona meglio nei sistemi online perché di solito recuperi o inverti solo un piccolo numero di righe, quindi dover "ritagliare" quegli spazi finali che otterrai nel set di risultati è un compito banale invece di dover unire milioni di righe righe da una tabella a milioni di righe su un'altra tabella.

Un altro motivo per cui CHAR ha senso rispetto a varchar sui sistemi online è che riduce le suddivisioni delle pagine.Usando char, stai essenzialmente "riservando" (e sprecando) quello spazio, quindi se un utente arriva più tardi e inserisce più dati in quella colonna, SQL ha già allocato spazio per esso e va lì.

Un altro motivo per utilizzare CHAR è simile al secondo motivo.Se un programmatore o un utente esegue un aggiornamento "batch" su milioni di righe, aggiungendo ad esempio qualche frase a un campo nota, non riceverai una chiamata dal tuo DBA nel cuore della notte chiedendoti perché le loro unità sono piene.In altre parole, porta a una crescita più prevedibile delle dimensioni di un database.

Quindi questi sono 3 modi in cui un sistema online (OLTP) può trarre vantaggio da char su varchar.Non utilizzo quasi mai char in uno scenario di magazzino/analisi/OLAP perché di solito hai così tanti dati che tutte quelle colonne char possono sommarsi a molto spazio sprecato.

Tieni presente che char può rendere il tuo database molto più grande, ma la maggior parte degli strumenti di backup dispone di compressione dei dati, quindi i tuoi backup tendono ad avere all'incirca le stesse dimensioni di se avessi utilizzato varchar.Ad esempio LiteSpeed ​​o RedGate SQL Backup.

Un altro utilizzo è nelle viste create per esportare dati in un file a larghezza fissa.Diciamo che devo esportare alcuni dati in un file flat per essere letto da un mainframe.La larghezza è fissa (non delimitata).Mi piace memorizzare i dati nella mia tabella di "staging" come varchar (consumando così meno spazio sul mio database) e quindi utilizzare una vista per CAST tutto al suo equivalente in caratteri, con la lunghezza corrispondente alla larghezza della larghezza fissa per quella colonna .Per esempio:

create table tblStagingTable (
pkID BIGINT (IDENTITY,1,1),
CustomerFirstName varchar(30),
CustomerLastName varchar(30),
CustomerCityStateZip varchar(100),
CustomerCurrentBalance money )

insert into tblStagingTable
(CustomerFirstName,CustomerLastName, CustomerCityStateZip) ('Joe','Blow','123 Main St Washington, MD 12345', 123.45)

create view vwStagingTable AS
SELECT CustomerFirstName = CAST(CustomerFirstName as CHAR(30)),
CustomerLastName = CAST(CustomerLastName as CHAR(30)),
CustomerCityStateZip = CAST(CustomerCityStateZip as CHAR(100)),
CustomerCurrentBalance = CAST(CAST(CustomerCurrentBalance as NUMERIC(9,2)) AS CHAR(10))

SELECT * from vwStagingTable

Questo è interessante perché internamente i miei dati occupano meno spazio perché utilizzano varchar.Ma quando utilizzo DTS o SSIS o anche solo un taglia e incolla da SSMS a Blocco note, posso utilizzare la visualizzazione e ottenere il numero corretto di spazi finali.In DTS avevamo una funzionalità chiamata, accidenti, non ricordo, penso che si chiamasse "suggerisci colonne" o qualcosa del genere.In SSIS non puoi più farlo, devi definire noiosamente la gestione connessione file flat.Tuttavia, poiché hai configurato la visualizzazione, SSIS può conoscere la larghezza di ogni colonna e può risparmiare molto tempo durante la creazione delle attività del flusso di dati.

Quindi, in conclusione...usa varchar.Esistono pochissimi motivi per utilizzare char ed è solo per motivi di prestazioni.Se hai un sistema con centinaia di milioni di righe vedrai una differenza notevole se i predicati sono deterministici (char), ma per la maggior parte dei sistemi utilizzare char significa semplicemente sprecare spazio.

Spero che aiuti.Jeff

Ci sono vantaggi in termini di prestazioni, ma eccone uno che non è stato menzionato:migrazione delle righe.Con char, prenoti l'intero spazio in anticipo. Quindi diciamo che hai un char (1000) e memorizzi 10 caratteri, utilizzerai tutti i 1000 caratteri dello spazio.In un varchar2(1000), utilizzerai solo 10 caratteri.Il problema sorge quando si modificano i dati.Supponiamo che tu aggiorni la colonna in modo che ora contenga 900 caratteri.È possibile che lo spazio per espandere il varchar non sia disponibile nel blocco corrente.In tal caso, il motore DB deve migrare la riga in un altro blocco e creare un puntatore nel blocco originale alla nuova riga nel nuovo blocco.Per leggere questi dati, il motore DB dovrà ora leggere 2 blocchi.
Nessuno può dire in modo equivoco che varchar o char siano migliori.C’è uno spazio per un compromesso temporale e per valutare se i dati verranno aggiornati, soprattutto se ci sono buone probabilità che crescano.

Esiste una differenza tra l'ottimizzazione iniziale delle prestazioni e l'utilizzo di un tipo di regola basata su best practice.Se stai creando nuove tabelle in cui avrai sempre un campo a lunghezza fissa, ha senso utilizzare CHAR, in questo caso dovresti utilizzarlo.Non si tratta di un'ottimizzazione iniziale, ma piuttosto dell'implementazione di una regola empirica (o delle migliori pratiche).

cioè.- Se il campo stato è composto da 2 lettere, utilizzare CHAR(2).Se hai un campo con i nomi degli stati effettivi, usa VARCHAR.

Sceglierei varchar a meno che la colonna non memorizzi un valore fisso come il codice dello stato degli Stati Uniti, che è sempre lungo 2 caratteri e l'elenco dei codici degli stati degli Stati Uniti validi non cambia spesso :).

In ogni altro caso, anche se si memorizza la password con hash (che ha una lunghezza fissa), sceglierei varchar.

Perché: la colonna di tipo char è sempre completata da spazi, il che costituisce la colonna mia_colonna definito come char(5) con valore 'ABC' all'interno del confronto:

my_column = 'ABC' -- my_column stores 'ABC  ' value which is different then 'ABC'

falso.

Questo caratteristica potrebbe portare a molti bug irritanti durante lo sviluppo e rendere i test più difficili.

CHAR occupa meno spazio di archiviazione di VARCHAR se tutti i valori dei dati in quel campo hanno la stessa lunghezza.Ora forse nel 2009 un database da 800 GB è uguale a tutti gli effetti di un 810 GB se si convertono i VARCHAR in CHAR, ma per stringhe brevi (1 o 2 caratteri), CHAR è ancora una "migliore pratica" del settore, direi.

Ora, se osservi l'ampia varietà di tipi di dati forniti dalla maggior parte dei database anche solo per i numeri interi (bit, tiny, int, bigint), CI SONO motivi per sceglierne uno rispetto all'altro.Scegliere semplicemente bigint ogni volta significa in realtà ignorare un po’ gli scopi e gli usi del campo.Se un campo rappresenta semplicemente l'età di una persona in anni, un bigint è eccessivo.Ora non è necessariamente "sbagliato", ma non è efficiente.

Ma è un argomento interessante e, man mano che i database migliorano nel tempo, si potrebbe sostenere che CHAR vs VARCHAR diventa meno rilevante.

Confermo il commento di Jim McKeeth.

Inoltre, l'indicizzazione e la scansione completa della tabella sono più veloci se la tabella ha solo colonne CHAR.Fondamentalmente l'ottimizzatore sarà in grado di prevedere quanto è grande ogni record se ha solo colonne CHAR, mentre deve controllare il valore della dimensione di ogni colonna VARCHAR.

Inoltre, se aggiorni una colonna VARCHAR a una dimensione maggiore rispetto al contenuto precedente, potresti forzare il database a ricostruire i suoi indici (perché hai forzato il database a spostare fisicamente il record sul disco).Mentre con le colonne CHAR ciò non accadrà mai.

Ma probabilmente non ti interesserà il calo delle prestazioni a meno che il tuo tavolo non sia enorme.

Ricorda le sagge parole di Djikstra.L’ottimizzazione anticipata delle prestazioni è la radice di tutti i mali.

Molte persone hanno sottolineato che se si conosce la lunghezza esatta del valore, l'utilizzo di CHAR presenta alcuni vantaggi.Ma mentre memorizzare gli stati degli Stati Uniti come CHAR(2) è fantastico oggi, quando ricevi il messaggio dalle vendite che "Abbiamo appena effettuato la nostra prima vendita in Australia", sei in un mondo di dolore.Mando sempre a sovrastimare la durata che penso debbano durare i campi piuttosto che fare un'ipotesi "esatta" per coprire eventi futuri.VARCHAR mi darà maggiore flessibilità in quest'area.

C'è un piccolo sovraccarico di elaborazione nel calcolo della dimensione effettiva necessaria per un valore di colonna e nell'allocazione dello spazio per un Varchar, quindi se sei sicuro di quanto sarà sempre lungo il valore, è meglio usare Char ed evitare il risultato.

È il classico compromesso tra spazio e prestazioni.

In MS SQL 2005, Varchar (o NVarchar per le lingue che richiedono due byte per carattere, ad esempio il cinese) hanno una lunghezza variabile.Se si aggiunge alla riga dopo che è stata scritta sul disco rigido, i dati verranno individuati in una posizione non contigua alla riga originale e ciò causerà la frammentazione dei file di dati.Ciò influirà sulle prestazioni.

Quindi, se lo spazio non è un problema, i Char sono migliori in termini di prestazioni, ma se si desidera mantenere ridotte le dimensioni del database, i varchar sono migliori.

Penso che nel tuo caso probabilmente non ci sia motivo di non scegliere Varchar.Ti dà flessibilità e, come è stato menzionato da numerosi intervistati, le prestazioni sono tali ora che, tranne in circostanze molto specifiche, noi comuni mortali (al contrario dei DBA di Google) non noteremo la differenza.

Una cosa interessante che vale la pena notare quando si tratta di tipi di DB è che sqlite (un popolare mini database con prestazioni davvero impressionanti) inserisce tutto nel database come una stringa e digita al volo.

Uso sempre VarChar e di solito lo rendo molto più grande di quanto potrei aver strettamente bisogno.Per esempio.50 per Nome, come dici tu, perché non solo per sicurezza.

Frammentazione.Char riserva spazio e VarChar no.Può essere necessaria la suddivisione della pagina per consentire l'aggiornamento a varchar.

Non userei MAI i caratteri.Ho avuto questo dibattito con molte persone e loro tirano sempre fuori lo stanco cliché secondo cui il carboncino è più veloce.Beh, dico, quanto più velocemente?Di cosa stiamo parlando qui, millisecondi, secondi e se sì di quanti?Mi stai dicendo che, poiché qualcuno afferma che è qualche millisecondo più veloce, dovremmo introdurre tonnellate di bug difficili da correggere nel sistema?

Quindi ecco alcuni problemi che incontrerai:

Ogni campo verrà riempito, quindi ti ritroverai con codice per sempre che ha RTRIMS ovunque.Questo è anche un enorme spreco di spazio su disco per i campi più lunghi.

Ora supponiamo che tu abbia l'esempio per eccellenza di un campo char di un solo carattere ma il campo è facoltativo.Se qualcuno passa una stringa vuota a quel campo, diventa uno spazio.Pertanto, quando un'altra applicazione/processo lo interroga, ottiene un singolo spazio, se non utilizza rtrim.Abbiamo avuto documenti XML, file e altri programmi, che visualizzavano solo uno spazio, in campi opzionali e interrompevano le cose.

Quindi ora devi assicurarti di passare valori nulli e non stringhe vuote al campo char.Ma NON è l’uso corretto di null.Ecco l'uso di null.Supponiamo che tu riceva un file da un fornitore

Nome|Sesso|Città

Bob||Los Angeles

Se il sesso non è specificato, inserisci Bob, una stringa vuota e Los Angeles nella tabella.Ora diciamo che ottieni il file e il suo formato cambia e il genere non è più incluso ma era in passato.

Nome|Città

Bob|Seattle

Bene, poiché il genere non è incluso, utilizzerei null.I Varchar lo supportano senza problemi.

Char d'altra parte è diverso.Devi sempre inviare null.Se mai invii una stringa vuota, ti ritroverai con un campo che contiene spazi.

Potrei andare avanti all'infinito con tutti i bug che ho dovuto correggere dai caratteri e in circa 20 anni di sviluppo.

Quando si utilizza Varchar Values ​​SQL Server necessita di altri 2 byte per riga per archiviare alcune informazioni su quella colonna, mentre se si utilizza Char non ne ha bisogno, a meno che tu

In alcuni database SQL, VARCHAR verrà riempito alla sua dimensione massima per ottimizzare gli offset, questo per accelerare le scansioni e gli indici completi della tabella.

Per questo motivo, non si ottiene alcun risparmio di spazio utilizzando un VARCHAR(200) rispetto a un CHAR(200)

L'utilizzo di CHAR (NCHAR) e VARCHAR (NVARCHAR) comporta differenze nel modo in cui il server del database memorizza i dati.Il primo introduce spazi finali;Ho riscontrato problemi durante l'utilizzo con l'operatore LIKE nelle funzioni SQL SERVER.Quindi devo renderlo sicuro utilizzando sempre VARCHAR (NVARCHAR).

Ad esempio, se abbiamo un tavolo TEST(ID INT, Stato CHAR(1)), e scrivi una funzione per elencare tutti i record con un valore specifico come il seguente:

CREATE FUNCTION List(@Status AS CHAR(1) = '')
RETURNS TABLE
AS
RETURN
SELECT * FROM TEST
WHERE Status LIKE '%' + @Status '%'

In questa funzione ci aspettiamo che quando inseriamo il parametro predefinito la funzione restituisca tutte le righe, ma in realtà non è così.Cambiare il tipo di dati @Status in VARCHAR risolverà il problema.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top