2009-12-16 6 views
2

question rapide pour le sortir du DBA là:SQL indexation - colonne calculée vs champ utilisé par colonne calculée

Dire que j'ai 2 colonnes sur ma table, IsDeleted (bit) et DeletedDate (datetime). La table contient environ 10 000 000 lignes. IsDeleted est une colonne calculée qui vérifie si DeletedDate est NULL; et il renvoie 1 s'il ne l'est pas, et 0 s'il l'est.

L'interrogation de cette table se fera principalement sur la colonne IsDeleted.

Quelqu'un pourrait-il me donner quelques suggestions sur où je devrais appliquer mon index? L'application à la zone IsDeleted entraîne une série de problèmes dus à la désactivation de l'IDENTIFIANT QUOTED SET, qui n'est pas nécessairement un facteur de rupture, mais qui entraînerait un travail supplémentaire. Est-ce que je verrais un avantage à l'appliquer à DeletedDate, même si je n'interroge pas directement ce champ? Devrais-je juste mordre la balle et l'ajouter à IsDeleted? La différence de performance entre les deux est-elle négligeable?

Merci encore; et si vous souhaitez des clarifications; laissez-moi un commentaire et je mettrai à jour mon message.

Répondre

3

Cela n'a pas de sens de placer un index sur une colonne de bits car elle n'est pas assez sélective. Lors de l'exécution d'une requête, SQL Server détermine les index les plus appropriés à utiliser. Si votre index n'est pas assez sélectif, il sera ignoré ou il peut décider de faire un scan d'index au lieu d'une recherche d'index. De toute façon, ça ne va pas vraiment aider beaucoup. Mettre l'index sur le DeletedDate pourrait aider avec quelques requêtes, mais le filtrage sur NULL contre "n'importe quelle valeur" ne sera probablement pas beaucoup d'aide non plus à cause de la sélectivité.

Je vous invite à lire ceci: Seek Vs. Scan

0

Je ne pense pas que vous verriez un avantage à l'ajouter à DeletedDate. Cependant, si vous n'êtes pas sûr, il devrait être assez facile de tester la performance dans les deux sens.

1

Placer un index sur un attribut dont les valeurs sont limitées à un très petit domaine (évidemment deux valeurs est la plus petite possible) n'a pas de sens, sauf pour le bord spécial cas, (comme lorsque les lignes sont distribuées 90% -10% entre les 2 valeurs)

Cela est dû au fait que toute utilisation de l'index pour trouver l'une des valeurs (en supposant que les lignes sont réparties uniformément environ 50-50) retournera environ la moitié du nombre total de lignes dans la table. Si l'index de l'arbre équilibré (B-Tree) que vous créez est à trois ou quatre niveaux de profondeur, cela signifie que 3 ou 4 opérations d'E/S par ligne seront récupérées, ce qui serait plus que le nombre de lignes de la table.

1

Vous ne pouvez pas mettre un index sur IsDeleted si le calcul est basé sur le datetime actuel, car le résultat de la colonne calculée est non déterministe. Il est basé sur le temps et a potentiellement un résultat différent à chaque invocation.Voir cette msdn article pour plus de détails:

Par exemple, si la table a entier colonnes a et b, la colonne calculée a + b peut être indexé, mais calculé colonne a + DATEPART (dd, GETDATE() ne peut pas être indexé car la valeur peut changer lors d'invocations ultérieures.

Si la date comparer devient trop cher, vous devrez planifier une déclaration de mise à jour pour le temps d'exécution tous les « x » pour définir la valeur IsDeleted pour « expiré » dates:

UPDATE MyTable SET IsDeleted=1 WHERE IsDeleted=0 AND DeletedDate < getutcdate() 

Modifier: J'ai mal lu la question initialement, lorsque le calcul est NULL vs non-NULL, il sera déterministe. Avec un résultat déterministe, le mot-clé PERSISTED peut être utilisé pour stocker le résultat du contrôle nul:

IsDeleted AS DeletedDate IS NOT NULL PERSISTED 

Cela évite l'exécution des vérifications nuls datetime tout le temps. Il stocke le résultat dans la table, jusqu'à ce que vous mettiez à jour la colonne DeletedDate. Vous devez tester si cela est payant, cependant, je ne pense pas que le test DeletedDate NULL sera très cher.

L'indexation de l'une ou l'autre propriété n'a probablement pas beaucoup de sens car vous souhaitez essentiellement séparer 2 groupes: supprimé et non supprimé.

+0

Est-ce vrai? Vérifier si le champ est nul ou non ne semble pas logiquement non-déterministe. –

+0

oh j'ai mal compris cela, je pensais que vous étiez en train de comparer DeletedDate avec la date actuelle, Wonder pour éditer, ou tirez la réponse et re-répondre –

1

Dites la distribution est: 98% IsDeleted = 0 2% IsDeleted = 1

SQL Server serait être assez intelligent pour ne stocker que les informations pour les enregistrements isDeleted dans un indice?

Questions connexes