2009-06-01 4 views
2

Il est nécessaire d'utiliser GUID (s) comme clés primaires. Ai-je raison de penser queguid Création d'une clé primaire pour la requête la plus rapide sélectionnez où guid (guid1, guid2, guid3 ...)

ProductID UNIQUEIDENTIFIER NOT NULL 
ROWGUIDCOL DEFAULT (NEWSEQUNTIALID()) PRIMARY KEY CLUSTERED 

donnera le plus rapide de sélection pour where

productid in (guid1 , guid2 ,..., guidn)

et ne se détériore pas non cluster

natural_key like 'Something*'

select indépendant. Table à interroger uniquement par les utilisateurs et créé/recréé par programmation à partir de zéro.

Répondre

0

Un index cluster est le mieux adapté à la gamme des recherches, il pourrait satisfaire votre requête:

productid in (guid1 , guid2 ,..., guidn) 

mais dépend ce que vous sélectionnez, regroupement par, commande par etc si l'indice est d'être une couverture indice. Sinon, un autre index non groupé peut être sélectionné par l'optimiseur suivi d'une recherche dans l'index clusterisé. Cela dépend aussi dans une certaine mesure du nombre de lignes dans cette table.

Aussi, je pense que vous pouvez utiliser NEWID() comme opposer NEWSEQUENTIALID()

+1

Une liste disparate de valeurs distinctes dans une instruction IN n'est pas exactement une requête de plage .... –

+0

@marc_s: c'est un bon point! Mais ce sont des GUID séquentiels, tels que posés dans la question initiale, donc je pense qu'ils peuvent se présenter comme une gamme. –

+0

La séquence d'origine est aléatoire telle que renvoyée par l'index de texte intégral Lucene.Net, mais si elle accélère une requête, aucun problème pour trier les GUID en mémoire. – MicMit

3

Le fait que vous utilisez des années GUID comme un index ordonné en clusters sera très certainement un impact négatif sur votre performance. Même avec le NEWSEQUENTIALGUID, les GUID ne sont pas vraiment séquentiels - ils ne le sont que partiellement. Leur nature aléatoire conduira certainement à une fragmentation de l'indice plus élevée et donc à des temps de recherche moins optimaux. De plus, si vous disposez d'un GUID de 16 octets comme clé en cluster, il sera ajouté à tout index non cluster de cette table. Cela peut ne pas sembler si mauvais, mais si vous avez 10 mio. lignes, 10 index non clusterisés, utilisant un GUID de 16 octets par rapport à un INT de 4 octets vous coûtera 1,2 Go de stockage gaspillé - et pas seulement sur disque (ce qui est bon marché), mais aussi dans la mémoire de votre serveur SQL (depuis Le serveur SQL charge toujours des pages entières de 8 ko dans des blocs de mémoire de 8 ko, qu'ils soient pleins ou vides.

Je peux voir le point d'utiliser un GUID comme une clé primaire - ils sont presque 100% garantie d'être unique est attrayant pour les développeurs. MAIS: comme une clé en cluster, ils sont un cauchemar pour votre base de données.

Ma meilleure pratique: si j'ai vraiment besoin d'un GUID comme clé primaire, j'ajoute une INT INTENTION de 4 octets à la table qui sert alors de clé groupée - les résultats sont bien meilleurs! Si vous disposez d'une clé primaire non groupée, vos requêtes utilisant la liste des GUID seront tout aussi rapides que si vous utilisez une clé primaire en cluster et si vous n'utilisez pas de GUID pour votre clé en cluster, votre table fonctionnera mieux à la fin.

Lisez plus sur la touche en cluster et pourquoi il est si important de choisir le bon dans le blog de Kimberly Tripps - la la reine d'indexation et peut expliquer les choses beaucoup mieux que moi:

Marc

+0

Pouvons-nous dire qu'en général si GUID est la clé primaire, il devrait être non-cluster, avoir clusterisé ne donne aucun avantage pour select dans la requête. Dans le cas où il a été omis pour mon application, la table est recréée à partir de zéro à chaque fois, les utilisateurs l'interrogent juste une fois qu'il est prêt. – MicMit

1

De même que les GUID étant mauvais (réponse de marc_s), vous avez également une clause IN. Cela descend jusqu'à:

productid = guid1 OR productid = guid2 OR ... OR productid = guidn 

... en pratique, ce qui n'est pas optimal non plus.

Généralement, natural_key like 'Something%' sera probablement mieux pour un index clusterisé sur votre colonne de clé natrual.

+0

pour des requêtes comme celles-ci, j'aime diviser la liste IN csv en une table et ensuite juste la joindre pour qu'elle utilise un index. –

+0

Merci, j'utilise la même idée si je dois utiliser CSV – gbn

Questions connexes