2009-10-21 9 views
7

Ceci est un FAIT Table dans un entrepôt de donnéesPerformance indexation BigInt vs VarChar

Il a un indice composite comme suit

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 

Dans cette structure, tous les varchar 10 colonnes ont valeurs numériques seulement. Serai-je bénéfique pour moi de changer cette structure de 78 millions de lignes pour contenir BIGINT au lieu de VARCHAR en termes d'interrogation et d'indexation?

D'autres avantages/inconvénients que je devrais envisager?

Répondre

14

Vous devez DEFINITIVEMENT introduire une clé primaire INT IDENTITY() de remplacement !! INT vous donne déjà potentiellement jusqu'à 2 milliards de lignes - n'est-ce pas suffisant ?? Cette clé primaire/clé clusterisée sur SQL Server aura une taille maximale de 64 octets (au lieu de 4, pour un INT) - ce qui fera gonfler votre index clusterisé et tout votre index non clusterisé au-delà de la reconnaissance. La clé de clustering complète (toutes vos 8 colonnes) sera incluse sur chaque page de chaque index non clusterisé de cette table - gaspillant beaucoup d'espace à coup sûr. Donc, sur une table d'index donnée, vous auriez jusqu'à 16 fois plus d'entrées avec une clé de cluster INT substitut - cela signifie beaucoup moins d'E/S, beaucoup moins de temps perdu à lire les pages d'index. Imaginez simplement que vous essayez d'établir une relation de clé étrangère avec cette table .... toute table enfant doit avoir toutes les colonnesde votre clé primaire en tant que colonnes de clé étrangère et spécifier les 8 colonnes de chaque table. rejoindre - quel cauchemar !! Avec 78 millions de lignes, même en changeant simplement la clé de clustering pour INT IDENTITY, vous économiserez jusqu'à 60 octets par ligne, ce qui représenterait jusqu'à 4 Go d'espace disque (et l'utilisation de la RAM sur votre serveur) . Et cela ne commence même pas à calculer les économies sur les indices non-cluster ...

Et bien sûr, oui, je voudrais aussi changer le VARCHAR (10) en INT ou BIGINT - si c'est un nombre , faites le type de champ numérique - aucun point en le laissant à VARCHAR (10), vraiment. Mais cela seul ne va pas faire une énorme différence en termes de vitesse ou de performance - cela rend simplement le travail avec les données beaucoup plus facile (ne pas avoir à passer à des types numériques, par exemple en comparant des valeurs et ainsi de suite).

Marc

+1

Ceci est une table de faits dans mon entrepôt de données. il n'y a pas de tables utilisant le PK à partir de cela comme un FK. –

+0

@Raj: ah, ok, cela explique quelques petites choses - vous avez oublié de le mentionner. Mais encore: avez-vous des indices non-cluster sur cette table, aussi? Ceux-ci seraient certainement énormément d'avoir une seule clé INT/BIGINT primaire/clustering –

+0

Bigint utilise 64 BITS pas octets, c'est-à-dire qu'il est deux fois plus grand, pas 16 fois. – Yrlec

1

Marc S est juste en ce que la clé primaire de 64 octets va être dupliqué dans tous les indices NC afin que vous allez payer un coût d'E/S, ce qui aura un impact sur la quantité de données est conservé en mémoire (puisque vous gaspillez de l'espace sur une page d'index NC). Donc, sur cette base, la question n'est pas "devrais-je convertir mes varchars" mais "devrais-je envisager de convertir mon index clusterisé en quelque chose de complètement différent."

En termes de varchar vs bigint il y a une bonne raison de convertir si vous pouvez vous permettre le temps; En dehors de la différence de stockage de 2 octets par champ, lorsque vous comparez des valeurs de deux types différents, SQL sera forcé de convertir l'un d'entre eux. Cela se produirait à chaque comparaison, que ce soit pour une jointure d'index ou un prédicat dans une clause where.En fonction de ce que vous sélectionnez les données, quelles tables de dimension sont jointes à la table de faits, vous pouvez récupérer les frais généraux de conversion pour chaque requête, pour qu'elle soit jointe, car elle doit convertir un côté de il.

4

Deux choses qui peuvent avoir une incidence sur l'indice (et DB global) performance:

1) Taille de la page d'index 2) Comparaison de la vitesse

Donc, pour le premier, en général, le plus petit index/données la page est, plus vous pouvez stocker de pages en mémoire, et plus grande est la probabilité qu'une requête donnée puisse trouver la page en cache par rapport au disque lent. Ainsi, vous voudrez utiliser le plus petit type de données qui peut s'adapter confortablement à vos besoins futurs existants et proposés.

BigInt est de 8 octets; VARCHAR peut être plus petit si la taille des données est petite, donc cela dépend vraiment de vos données. Toutefois, des nombres longs de 10 caractères peuvent être adaptés au type de données INT de SQL Server (http://msdn.microsoft.com/en-us/library/ms187745.aspx) en fonction de la taille, de sorte que int vs. bigint dépend de votre domaine. En outre, si votre ligne entière est d'une longueur fixe, SQL Server peut effectuer certaines optimisations dans les analyses car elle sait exactement où se trouvera sur la disquette la prochaine ligne (en supposant que les lignes sont contiguës). Un cas de bord, pour être sûr, mais cela peut aider.

Pour le second, il est plus rapide de comparer des entiers que des chaînes Unicode. Donc, si vous ne stockez que des données numériques, vous devriez définitivement passer à un type de données numériques de taille appropriée. Enfin, Marc a raison de dire que cela devient une clé primaire très alambiquée. Cependant, si vos données le justifient - comme ce sont vos seules colonnes et vous ne faites jamais de requêtes add'l - vous pouvez parfaitement faire de la version optimisée (avec Bigints etc.) votre clé primaire. Une sorte d'odeur de code, cependant, donc je vais faire écho à ses conseils pour vraiment jeter un oeil à votre modèle de données et voir si c'est correct.