Ma connaissance de niveau inférieur de SQL (Server 2008) est limitée et est maintenant remise en question par nos DBA. Permettez-moi d'expliquer (j'ai mentionné des déclarations évidentes dans l'espoir d'avoir raison, mais si vous voyez quelque chose qui ne va pas, dites-moi s'il vous plaît) le scénario:
Nous avons une table qui contient des «ordonnances judiciaires» pour les gens. Lorsque j'ai créé la table, (Nom: CourtOrder), je l'ai créée comme:
CREATE TABLE dbo.CourtOrder
(
CourtOrderID INT NOT NULL IDENTITY(1,1), (Primary Key)
PersonId INT NOT NULL,
+ around 20 other fields of different types.
)
J'ai ensuite appliqué un index non clusterisé à la clé primaire (pour plus d'efficacité). Ma raison est qu'il s'agit d'un champ unique (clé primaire), et devrait être indexé, principalement à des fins de sélection, comme nousSelect from table where primary key = ...
J'ai ensuite appliqué un index CLUSTERED sur PersonId. La raison était de regrouper physiquement les commandes d'une personne en particulier, car la grande majorité du travail consiste à obtenir des commandes pour une personne. Alors,select from mytable where personId = ...
J'ai été tiré dessus maintenant. On m'a dit que nous devrions mettre l'index clusterisé sur la clé primaire et l'index normal sur le personId. Cela me semble très étrange. Tout d'abord, pourquoi placeriez-vous un index clusterisé sur une colonne unique? qu'est-ce que le clustering? C'est sûrement un gaspillage de l'index clusterisé? J'aurais cru qu'un index normal serait utilisé sur une colonne unique. De plus, le regroupement de l'index signifierait que nous ne pouvons pas regrouper une colonne différente (une par table, non?).
Le raisonnement pour lequel on me dit que j'ai fait une erreur est qu'ils pensent que mettre un index groupé sur PersonId ralentirait les insertions. Pour le gain de vitesse de 5% d'une sélection, nous obtiendrions une dégradation de 95% de la vitesse sur les insertions et les mises à jour. Est-ce correct et valide?
Ils disent que parce que nous regroupons le personId, SQL Server doit réorganiser les données chaque fois que nous insérons ou modifions le PersonId.
Alors j'ai demandé, pourquoi SQL aurait-il le concept d'un INDEX CLUSTERED, si c'est si lent? Est-ce aussi lent qu'ils le disent? Comment dois-je configurer mes index pour obtenir des performances optimales? J'aurais pensé que SELECT était plus utilisé que INSERT ... mais ils disent que nous avons des problèmes de verrouillage sur INSERTS ...
J'espère que quelqu'un pourra m'aider.
Réponses:
La distinction entre un index clusterisé et non clusterisé est que l'index cluster détermine l'ordre physique des lignes dans la base de données . En d'autres termes, appliquer l'index clusterisé à
PersonId
signifie que les lignes seront physiquement triéesPersonId
dans la table, ce qui permet à une recherche d'index à ce sujet d'aller directement à la ligne (plutôt qu'à un index non groupé, qui vous dirigerait vers la ligne. emplacement, en ajoutant une étape supplémentaire).Cela dit, il est inhabituel que la clé primaire ne soit pas l'index clusterisé, mais ce n'est pas inconnu. Le problème avec votre scénario est en fait le contraire de ce que vous supposez: vous voulez des valeurs uniques dans un index clusterisé, pas des doublons. Étant donné que l'index cluster détermine l'ordre physique de la ligne, si l'index est sur une colonne non unique, le serveur doit ajouter une valeur d'arrière-plan aux lignes qui ont une valeur de clé en double (dans votre cas, toutes les lignes avec la même valeur
PersonId
) afin que la valeur combinée (clé + valeur d'arrière-plan) soit unique.La seule chose que je suggérerais est de ne pas utiliser une
CourtOrderId
colonne de clé de substitution (votre ) comme clé primaire, mais plutôt d'utiliser une clé primaire composée de laPersonId
et d'une autre colonne ou d'un ensemble de colonnes à identification unique. Si ce n'est pas possible (ou pas pratique), activez l'index clusteriséCourtOrderId
.la source
PersonId
. Il est trié logiquement parPersonId
, tout écart entre l'ordre logique et physique est le degré de fragmentation logique.Je ne suis en aucun cas un expert SQL ... alors prenez cela comme une vue de développeur plutôt qu'une vue DBA.
Les insertions sur des index en cluster (ordonnés physiquement) qui ne sont pas dans l'ordre séquentiel entraînent un travail supplémentaire pour les insertions / mises à jour. De plus, si de nombreuses insertions se produisent en même temps et qu'elles se produisent toutes au même endroit, vous vous retrouvez avec une contention. Vos performances spécifiques varient en fonction de vos données et de la manière dont vous y accédez. La règle générale consiste à créer votre index clusterisé sur la valeur étroite la plus unique de votre table (généralement le PK)
Je suppose que votre PersonId ne changera pas, donc les mises à jour n'entrent pas en jeu ici. Mais considérons un instantané de quelques lignes avec PersonId de 1 2 3 3 4 5 6 7 8 8
Insérez maintenant 20 nouvelles lignes pour PersonId de 3. Premièrement, comme il ne s'agit pas d'une clé unique, le serveur ajoute quelques octets supplémentaires à votre valeur (dans les coulisses) pour la rendre unique (ce qui ajoute également de l'espace supplémentaire), puis l'emplacement où ceux-ci résideront doivent être modifiés. Comparez cela à l'insertion d'un PK auto-incrémenté où les insertions se produisent à la fin. L'explication non technique se résumerait probablement à ceci: il y a moins de travail de `` mélange de feuilles '' à faire s'il progresse naturellement des valeurs plus élevées à la fin du tableau que de retravailler l'emplacement des éléments existants à cet emplacement lors de l'insertion de vos éléments.
Maintenant, si vous rencontrez des problèmes avec les insertions, vous insérez probablement un tas de valeurs PersonId identiques (ou similaires) à la fois, ce qui provoque ce travail supplémentaire à divers endroits de la table et la fragmentation vous tue. L'inconvénient du passage au PK en cluster dans votre cas, c'est que si vous rencontrez des problèmes d'insertion aujourd'hui sur des PersonIds dont la valeur varie dans la table, si vous basculez votre index cluster sur le PK et que toutes les insertions se produisent maintenant en un emplacement, votre problème peut en fait s'aggraver en raison d'une concentration accrue de conflits. (D'un autre côté, si vos inserts aujourd'hui ne sont pas répartis partout, mais sont généralement regroupés dans des zones similaires, votre problème sera probablement atténué en faisant passer votre index cluster de PersonId à votre PK car vous minimiserez le fragmentation.)
Vos problèmes de performance doivent être analysés en fonction de votre situation particulière et ne prendre ces types de réponses que comme des directives générales. Votre meilleur pari est de compter sur un DBA qui peut valider exactement où se situent vos problèmes. Il semble que vous ayez des problèmes de conflit de ressources qui peuvent aller au-delà d'un simple ajustement d'index. Cela pourrait être le symptôme d'un problème beaucoup plus vaste. (Problèmes de conception probables ... sinon limitations de ressources.)
Dans tous les cas, bonne chance!
la source
Certains auteurs suggèrent de ne pas «gaspiller» le
CI
sur uneidentity
colonne s'il existe une alternative qui profiterait aux requêtes de plage.D'après les directives de conception d'index en cluster MSDN, la clé doit être choisie en fonction des critères suivants
Votre
CourtOrderID
colonne se réunit2
. VosPersonId
rencontres1
et3
. Comme la plupart des lignes finiront avec l'uniqueifier
ajout de toute façon, vous pouvez tout aussi bien le déclarer comme unique et l'utiliserPersonId,CourtOrderID
car il aura la même largeur, mais sera plus utile car la clé d'index cluster est ajoutée à tous les NCI en tant que localisateur de lignes, ce qui permettra eux pour couvrir plus de requêtes.Le principal problème avec l'utilisation en
PersonId,CourtOrderID
tant que CI est que la fragmentation logique s'ensuivra probablement (et cela affecte particulièrement les requêtes de plage que vous essayez d'aider), vous devrez donc surveiller le facteur de remplissage et les niveaux de fragmentation et effectuer la maintenance de l'index plus souvent.la source
Il est expliqué dans le lien suivant: https://msdn.microsoft.com/en-us/ms190457.aspx
Clustered
Les index clusterisés trient et stockent les lignes de données dans la table ou la vue en fonction de leurs valeurs de clé. Ce sont les colonnes incluses dans la définition d'index. Il ne peut y avoir qu'un seul index clusterisé par table, car les lignes de données elles-mêmes ne peuvent être triées que dans un seul ordre.
Le seul moment où les lignes de données d'une table sont stockées dans un ordre trié est lorsque la table contient un index cluster. Lorsqu'une table a un index clusterisé, la table est appelée table clusterisée. Si une table n'a pas d'index clusterisé, ses lignes de données sont stockées dans une structure non ordonnée appelée tas.
Non clusterisé
Les index non clusterisés ont une structure distincte des lignes de données. Un index non clusterisé contient les valeurs de clé d'index non clusterisé et chaque entrée de valeur de clé a un pointeur vers la ligne de données qui contient la valeur de clé .
Le pointeur d'une ligne d'index dans un index non clusterisé vers une ligne de données est appelé un localisateur de lignes. La structure du localisateur de lignes varie selon que les pages de données sont stockées dans un tas ou dans une table en cluster. Pour un tas, un localisateur de ligne est un pointeur vers la ligne. Pour une table en cluster, le localisateur de lignes est la clé d'index cluster.
Vous pouvez ajouter des colonnes non clés au niveau feuille de l'index non clusterisé pour contourner les limites de clé d'index existantes, 900 octets et 16 colonnes clés, et exécuter des requêtes entièrement couvertes et indexées.
la source
Une certaine base de données avec des sélections désagréables se joint à une procédure stockée - seule la différence est l'index
INDEXES - en cluster ou non en cluster
la source