2009-10-21 17 views
7

Si tratta di una tabella FACT in un data warehouseindicizzazione delle prestazioni BigInt vs VarChar

Ha un indice composto come segue

ALTER TABLE [dbo].[Fact_Data] 
ADD CONSTRAINT [PK_Fact_Data] 
PRIMARY KEY CLUSTERED 
(
    [Column1_VarChar_10] ASC, 
    [Column2_VarChar_10] ASC, 
    [Column3_Int] ASC, 
    [Column4_Int] ASC, 
    [Column5_VarChar_10] ASC, 
    [Column6_VarChar_10] ASC, 
    [Column7_DateTime] ASC, 
    [Column8_DateTime] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON 
) ON [PRIMARY] 
GO 

In questa struttura, tutte le varchar 10 colonne hanno solo valori numerici. Sarà utile per me modificare questa struttura di 78 milioni di righe per contenere BIGINT anziché VARCHAR in termini di query e indicizzazione?

Eventuali altri vantaggi/svantaggi che dovrei prendere in considerazione?

risposta

14

È necessario DEFINITEL introdurre una chiave primaria sostitutiva INT IDENTITY() !! INT ti dà già potenzialmente fino a 2 miliardi di righe - non è abbastanza ??

Questa chiave primaria/chiave in cluster su SQL Server avrà una dimensione massima di 64 byte (invece di 4, per INT), il che renderà il vostro indice cluster E tutto il vostro indice non cluster gonfio oltre il riconoscimento. L'intera chiave di clustering (tutte le 8 colonne) sarà inclusa in ogni singola pagina di ogni singolo indice non cluster su quella tabella, sprecando sicuramente molto spazio.

Quindi, in qualsiasi tabella di indice fornita, si avranno fino a 16 volte più voci con una chiave cluster surrogata INT - ciò significa molto meno I/O, molto meno tempo sprecato nella lettura delle pagine indice.

E immagina solo di provare a stabilire una relazione di chiave esterna con quella tabella .... qualsiasi tabella figlio dovrebbe avere tutte le colonne 8 della chiave primaria come colonne di chiavi esterne e specificare tutte le 8 colonne in ogni unisciti - che incubo !!

A 78 milioni di righe, anche solo la semplice modifica della chiave di clustering a INT IDENTITY consente di risparmiare fino a 60 byte per riga, che da sola equivale a un massimo di 4 GB di spazio su disco (e utilizzo RAM nel server) . E questo non inizia nemmeno a calcolare i risparmi sugli indici non raggruppati .......

E naturalmente, sì, vorrei anche cambiare VARCHAR (10) in INT o BIGINT - se è un numero , rendi il campo di tipo numerico - nessun punto nel lasciarlo a VARCHAR (10), davvero. Ma questo da solo non farà un'enorme differenza in termini di velocità o prestazioni - semplifica il lavoro con i dati (non è necessario eseguire sempre il casting di tipi numerici per esempio confrontando i valori e così via).

Marc

+1

questa è una tabella dei fatti nel mio data warehouse. non ci sono tabelle che usano il PK da questo come un FK. –

+0

@Raj: ah, ok, questo spiega alcune cose - hai dimenticato di dirlo. Ma ancora: hai indici non cluster anche su questa tabella? Quelli sarebbero sicuramente enormemente dotati di una chiave INT primaria o BIGINT primaria/di clustering –

+0

Bigint utilizza 64 bit BITS, ovvero due volte più grande, non 16 volte. – Yrlec

1

Marc S si trova proprio di che la chiave primaria di 64 byte sta per essere ripetuto in ogni indice NC in modo che si sta per pagare un costo di I/O, che avrà un impatto sulla quantità di dati che è tenuto in memoria (dato che stai sprecando spazio su una pagina indice NC). Quindi su questa base la domanda non è "dovrei convertire i miei varchar" ma "dovrei considerare di convertire il mio indice cluster in qualcosa di completamente diverso./

In termini di varchar vs bigint c'è una buona ragione per convertire se puoi permetterti il ​​tempo; che è al di fuori della differenza di 2 byte nella memoria per campo, quando si confrontano valori che sono di due tipi diversi, SQL sarà costretto a convertirne uno. Ciò si verificherebbe su ogni singolo confronto, sia che si tratti di un indice di join, sia di un predicato all'interno di una clausola where.

A seconda della selezione dei dati, quali tabelle delle dimensioni vengono unite alla tabella dei fatti, è possibile raccogliere i costi generali di conversione su ogni query, perché si unisca, poiché è necessario convertire un lato di esso.

4

Due cose che possono influenzare indice (e DB complessiva) prestazione:

1) Dimensione della pagina di indice di velocità 2) Confronto

Così, per il primo, in generale, il più piccolo il vostro indice/dati la pagina è, più pagine è possibile tenere in memoria e maggiore è la probabilità che una determinata query sia in grado di trovare la pagina nella cache rispetto al disco lento. Pertanto, vorresti utilizzare il più piccolo tipo di dati che possa adattarsi comodamente alle tue esigenze attuali e future.

BigInt è 8 byte; i VARCHAR possono essere più piccoli se la dimensione dei dati è piccola, quindi dipende molto dai tuoi dati. Tuttavia, i 10 numeri lunghi possono essere in grado di adattarsi al tipo di dati INT di SQL Server (http://msdn.microsoft.com/en-us/library/ms187745.aspx) a seconda della dimensione, quindi int vs bigint dipende dal dominio.

Inoltre, se l'intera riga è di una lunghezza fissa, esistono alcune ottimizzazioni che SQL Server può eseguire nelle scansioni poiché sa esattamente dove si trova il disco nella riga successiva (supponendo che le righe siano contigue). Un caso limite, certo, ma può aiutare.

Per il secondo, è più veloce confrontare gli interi rispetto alle stringhe Unicode. Pertanto, se si memorizzano solo dati numerici, è necessario passare a un tipo di dati numerico di dimensioni appropriate.

Infine, Marc è corretto sul fatto che questa diventa una chiave primaria molto contorta. Tuttavia, se i tuoi dati lo giustificano, come se fossero le tue SOLO colonne e non stai mai aggiungendo altre domande, potresti essere perfettamente a posto con la tua versione principale ottimizzata (con Bigints, ecc.). Una specie di odore di codice, comunque, quindi farò eco al suo consiglio di dare un'occhiata al tuo modello di dati e vedere se è corretto.

Problemi correlati