2009-10-27 7 views
8

In che modo le colonne varchar vengono gestite internamente da un motore di database? Per una colonna definita come char (100), il DBMS alloca 100 byte contigui sul disco. Tuttavia, per una colonna definita come varchar (100), presumibilmente non è il caso, dal momento che l'intero punto di varchar non è di allocare più spazio di quanto richiesto per memorizzare il valore di dati effettivo memorizzato nella colonna. Quindi, quando un utente aggiorna una riga di database contenente una colonna vuota varchar (100) ad un valore costituito da 80 caratteri, ad esempio, da dove viene assegnato lo spazio per gli 80 caratteri? Sembra che le colonne varchar debbano comportare una discreta quantità di frammentazione delle righe effettive del database, almeno negli scenari in cui i valori delle colonne vengono inizialmente inseriti come vuoti o NULL e quindi aggiornati successivamente con valori effettivi. Questa frammentazione si traduce in prestazioni degradate sulle query di database, anziché utilizzare valori di tipo char, in cui lo spazio per le colonne archiviate nelle righe viene allocato in modo contiguo? Ovviamente l'utilizzo dei risultati varchar comporta meno spazio su disco rispetto all'utilizzo di char, ma si verifica un calo delle prestazioni durante l'ottimizzazione delle prestazioni delle query, in particolare per le colonne i cui valori vengono frequentemente aggiornati dopo l'inserimento iniziale?Il risultato di varchar in termini di prestazioni è dovuto alla frammentazione dei dati?

risposta

4

Le strutture di dati utilizzate all'interno di un motore di database sono molto più complesse di te Sì, ci sono problemi di frammentazione e problemi in cui l'aggiornamento di un varchar con un valore elevato può causare un calo di prestazioni, tuttavia è difficile spiegare/comprendere quali sono le implicazioni di tali problemi senza una piena comprensione delle strutture dati coinvolto.

Per MS SQL server si potrebbe desiderare di iniziare con la comprensione pagine - l'unità fondamentale di stoccaggio (vedi http://msdn.microsoft.com/en-us/library/ms190969.aspx)

In termini di implicazioni sulle prestazioni di correzioni vs tipi di archiviazione variabile sulle prestazioni ci sono un certo numero di punti di prendere in considerazione:

  • Utilizzando colonne di lunghezza variabile in grado di migliorare le prestazioni in quanto consente più righe per adattarsi in una singola pagina, il che significa meno legge
  • Utilizzando colonne di lunghezza variabile richiede particolare valori di offset, e la manutenzione di questi valori richiede s un leggero overhead, tuttavia questo overhead extra è generalmente trascurabile.
  • Un altro costo potenziale è il costo di aumentare le dimensioni di una colonna quando la pagina contenente la riga è quasi pieno

Come si può vedere, la situazione è piuttosto complessa - in generale però si può fidare della banca dati il motore è abbastanza bravo a gestire i tipi di dati variabili e dovrebbe essere il tipo di dati da scegliere quando potrebbe esserci una varianza significativa della lunghezza dei dati contenuti in una colonna.

A questo punto ho anche intenzione di raccomandare l'eccellente libro "Microsoft Sql Server 2008 Internals" per ulteriori informazioni su come le cose complesse come questa si ottengono davvero!

7

Nella tua domanda fai molte assunzioni che non sono necessariamente vere.

Il tipo di una colonna in qualsiasi DBMS non indica nulla sulla natura della memorizzazione di tali dati a meno che la documentazione non indichi chiaramente come vengono memorizzati i dati. Se questo non è indicato, non si sa come è memorizzato e il DBMS è libero di cambiare il meccanismo di archiviazione dal rilascio al rilascio.

Infatti alcuni database memorizzano internamente i campi CHAR come VARCHAR, mentre altri decidono su come archiviare la colonna in base alla dimensione dichiarata della colonna. Alcuni database archiviano VARCHAR con le altre colonne, alcuni con dati BLOB e altri implementano altri archivi. Alcuni database riscrivono sempre l'intera riga quando una colonna viene aggiornata, altri no. Alcuni pad VARCHAR consentono un aggiornamento futuro limitato senza spostare lo spazio di archiviazione.

Il DBMS è responsabile di capire come archiviare i dati e restituirli a voi in modo rapido e coerente. Mi stupisce sempre quante persone provano a pensare al database, generalmente prima di rilevare qualsiasi problema di prestazioni.

+0

+1: la domanda presuppone anche una quantità significativa di aggiornamento che espande i campi VARCHAR. Anche questo può essere - in alcune applicazioni - una percentuale di righe estremamente piccola. –

+0

Grazie per le risposte. La mia domanda di base era come il DBMS memorizza dati di lunghezza variabile, e le risposte me ne hanno fatto luce. Il DB in questione ha un numero di colonne piuttosto grandi che sono inizialmente vuote nell'inserimento e compilate in seguito, quindi la mia preoccupazione generale era come questo viene gestito dal DBMS, e possibili problemi di prestazioni dovuti al salto intorno al disco rispetto all'utilizzo di caratteri. –

+0

@E. Dipende interamente dal tuo DBMS ed è possibile che non pubblichino tali informazioni. Tuttavia, i più moderni DBMS sono a conoscenza di problemi come la frammentazione dei dati e includono ottimizzazioni per evitare la perdita di prestazioni. A meno che non rilevi un problema di prestazioni, lascerei che fosse il database a gestirlo per te.(A occhio e croce, immagino che la maggior parte dei DBMS scriverà la riga sulla memoria corrente se si adatta, o in una nuova memoria, se non lo fa, liberando la vecchia memoria, con più o meno le stesse prestazioni in entrambi Astuccio). –

3

La risposta dipenderà dal DBMS specifico. Per Oracle, è certamente possibile finire con la frammentazione sotto forma di "file concatenate" e ciò comporta una penalizzazione delle prestazioni. Tuttavia, è possibile mitigare ciò predistribuendo un po 'di spazio vuoto nei blocchi di tabella per consentire l'espansione dovuta agli aggiornamenti. Tuttavia, le colonne CHAR in genere rendono la tabella molto più grande, il che ha un suo impatto sulle prestazioni. CHAR ha anche altri problemi, come i confronti vuoti, il che significa che, in Oracle, l'uso del tipo di dati CHAR è quasi mai una buona idea.

2

La tua domanda è troppo generica perché diversi motori di database avranno un comportamento diverso. Se hai davvero bisogno di sapere questo, ti suggerisco di impostare un benchmark per scrivere un gran numero di record e cronometrare. Vorresti avere un numero di record sufficiente per scrivere almeno un'ora.

Come hai suggerito, sarebbe interessante vedere cosa succede se scrivi di inserire tutti i record con una stringa vuota ("") e poi aggiornali per avere 100 caratteri che sono ragionevolmente casuali, non solo 100 Xs.

Se si prova questo con SQLITE e non si riscontra alcuna differenza significativa, penso che sia improbabile che i server di database più grandi, con tutte le analisi e le ottimizzazioni in corso, siano peggio di SQLITE.

+0

SQLite è un perfetto esempio di ciò che stavo dicendo nel mio commento, sopra, sul non conoscere il meccanismo di archiviazione per i dati. Sotto il cofano, SQLite non ha nemmeno la memoria dattiloscritta - è possibile inserire dati simili a VARCHAR in qualsiasi tipo di colonna (anche INTEGER). –

+0

La domanda è: questo fa alcuna differenza per le prestazioni? Solo un test lo dirà di sicuro. Per prima cosa, gli sviluppatori di software potrebbero aver realizzato il potenziale di frammentazione e attenuarlo in qualche modo. Per un altro, il riempimento extra di caratteri a lunghezza fissa probabilmente causerà più I/O di file, ma anche questo può essere mitigato. È necessario confrontare le varianti per sapere se c'è una differenza significativa. –

1

In SQL Server varchar (tranne varchar (MAX)) viene generalmente archiviato insieme al resto dei dati della riga (nella stessa pagina se i dati della riga sono < 8KB e nella stessa misura se è < 64 KB. i grandi tipi di dati come TEXT, NTEXT, IMAGE, VARHCAR (MAX), NVARHCAR (MAX), XML e VARBINARY (MAX) vengono memorizzati separatamente

2

Questo sarà completamente specifico del database.

So che in Oracle il database riserva una determinata percentuale di ogni blocco per gli aggiornamenti futuri (il parametro PCTFREE). Ad esempio, se PCTFREE è impostato su 25%, un blocco verrà utilizzato solo per i nuovi dati finché non sarà pieno al 75%. Facendo ciò, si lascia spazio per le file a crescere. Se la fila cresce in modo tale che lo spazio riservato del 25% è completamente esaurito, si finisce con le righe concatenate e una penalità legata alle prestazioni. Se si scopre che una tabella ha un numero elevato di righe concatenate, è possibile ottimizzare PCTFREE per quella tabella. Se hai una tabella che non avrà mai alcun aggiornamento, un PCTFREE pari a zero avrebbe senso

Problemi correlati