2010-01-16 6 views
1

J'ai travaillé toute la journée sur l'optimisation d'une table SQL Server 2000 db avec ~ 9 millions de lignes. Ma seule expérience db a été avec des tables de quelques centaines de lignes, donc je n'ai jamais vraiment eu affaire à l'optimisation.Optimisation de table SQL Server 2000

Je fais des sélections et des mises à jour basées sur un nombre à 21 chiffres. En utilisant un type index char (21), les requêtes prennent plus de 2 secondes et le processus SQL Server prend 1.5gigs de RAM et 100% CPU. Avec un type bigint indexé, mes requêtes prennent quelques millisecondes et le processus prend ~ 100 Mo de RAM. Je veux juste comprendre ce qui se passe ici, est-ce normal, ou existe-t-il un moyen spécifique d'indexer un type de char pour de meilleures performances?

Heres certains de mes sql:

CREATE TABLE data 
(
    tableID int NOT NULL IDENTITY PRIMARY KEY, 
    tag char(21) NOT NULL UNIQUE, 
    dataColumn1 datetime NULL, 
    dataColumn2 char(8) NULL, 
    lastModified datetime NOT NULL 
) 

requête paramétrées de C#:

SELECT tag FROM data WHERE tag = @tag; 

Merci pour toute aide.

+0

Cela me semble bien, en supposant que ce soit une représentation précise et qu'il y ait un index sur 'tag' ... une autre suggestion, essayez un' DBCC FREEPROCCACHE' et 'DBCC DROPCLEANBUFFERS' avant de tester chaque requête, juste pour être Assurez-vous qu'il n'utilise pas les résultats mis en cache. Voir aussi si vous pouvez publier le plan d'exécution (SET SHOWPLAN ON). Si vous voyez une recherche d'index en cluster (ou une recherche d'index régulière) dans le plan et aucune analyse, recherche de signet ou recherche RID, il n'y a probablement pas grand chose à faire pour améliorer la vitesse. – Aaronaught

Répondre

1

Ce n'est vraiment pas inhabituel, SQL gère beaucoup mieux les chiffres que les caractères. Un champ bigInt utilise 8 octets, ce qui correspond parfaitement à une page de mémoire. Un champ char prend 21 octets, ce qui triple presque la quantité de stockage pour le mettre dans un index.

Une autre considération est l'index clustered? L'index clusterisé fonctionnera beaucoup plus rapidement qu'un index non cluster. Il y a beaucoup de facteurs supplémentaires à prendre en compte, au-delà de la simple déclaration générale selon laquelle les chiffres fonctionneront mieux et utiliseront moins d'espace dans l'index.

+0

Il est logique que ce soit plus lent, mais il devrait être légèrement plus lent. J'ai un index de clé primaire ainsi qu'un index sur la colonne en question. Les deux sont non-groupés puisque je sélectionne seulement des rangées simples. Ma compréhension est que les index clusterisés améliorent les performances sur les requêtes de plage uniquement. Depuis que j'ai beaucoup de mises à jour aussi bien, je pense que les requêtes en cluster prendraient un grand disque i/o hit de performance. – Matt

0

Mon argent est sur la possibilité que vous essayez d'interroger sur une fonction de la colonne de char, à savoir quelque chose comme:

SELECT Column 
FROM Table 
WHERE UPPER(CharColumn) = 'ABC' 

Il est évident que je devine juste, mais cela est une source commune de la performance problèmes avec char/varchar/nvarchar colonnes. Si vous écrivez des requêtes comme celle-ci, vous devez réaliser qu'encapsuler la colonne dans une fonction empêche SQL Server d'effectuer une recherche d'index.

Prenez également en compte le nombre de lignes que vous renvoyez réellement; 9 millions de lignes n'ont pas forcément beaucoup à avoir dans la table, mais même 100 000 lignes est une quantité énorme à avoir dans un ensemble de résultats. Parfois, le goulot d'étranglement ne fait que diffuser tous les résultats. Si rien de cela ne décrit votre problème, alors je suggère de mettre à jour votre message avec des informations sur le schéma, les index que vous avez, et la requête qui tourne lentement. Vous pouvez effectuer d'autres optimisations, bien que SQL Server 2000 se poursuive depuis des années. Vos options sont donc limitées.


Basé sur le schéma que vous avez publié, en supposant que vous avez un index sur la tag et pas d'autres colonnes colonne tag, que vous ne sélectionnez qui pourraient ne pas être couvert, que votre WHERE condition est simple égalité sur la tag colonne, et que le nombre de résultats retournés est raisonnablement faible, je ne pense pas qu'il y ait d'autres optimisations que vous pouvez faire. Vous avez pratiquement réduit cela au cas le plus simple possible.

+0

Je sélectionne et met à jour des lignes simples directement sur la colonne sans utiliser de fonction. J'ai deux index non groupés sur la table en question. Une clé primaire et un index simple sur la colonne à 21 chiffres. – Matt

+0

Plus de détails seraient toujours utiles. Je ne peux pas dire si l'index est un index de couverture, et parfois avoir beaucoup d'index (ou de grands) peut ralentir un peu les opérations de mise à jour. Je pense que je pourrais vous donner une meilleure réponse avec des informations spécifiques sur le schéma, les index et la requête (anonymisez-le si vous voulez). – Aaronaught

+0

également, sachez qu'un champ CHAR (21) est rembourré avec des espaces à sa longueur, par ex. vous ne trouverez pas de champ avec "ABC" dedans - plutôt, il contiendra "ABC ............................ ... "(où. représente un espace ici) –

1

comparaisons de caractères sont un peu plus lente - la séquence de classement doit être considéré - sans parler de la différence physique entre la taille d'une chaîne de 21 caractères et un bigint (8 octets). La recherche d'index ne peut pas être aussi efficace car elle doit évaluer chaque octet dans vos valeurs char (21), décider de l'ordre de tri du personnage, puis décider comment cela se compare au caractère correspondant dans la valeur que vous recherchez .

Un index cluster fonctionnera mieux pour presque toutes les requêtes parce que les données (y compris les pages d'index IIRC, je ne suis pas un DBA) sont dans l'ordre du disque cache. Ou du moins plus près.

+0

En fait, un index * scan * en cluster fonctionnera plus lentement qu'un scan d'index régulier; C'est pourquoi j'espérais plus de détails. – Aaronaught