Question

Si j'ai une requête du type :

Select EmployeeId 
From Employee 
Where EmployeeTypeId IN (1,2,3)

et j'ai un index sur le EmployeeTypeId champ, le serveur SQL utilise-t-il toujours cet index ?

Était-ce utile?

La solution

Oui c'est vrai.Si votre table d'employés contient 10 000 enregistrements et que seuls 5 enregistrements ont l'ID de type d'employé dans (1,2,3), elle utilisera très probablement l'index pour récupérer les enregistrements.Cependant, s'il constate que 9 000 enregistrements ont le type EmployeeIDType dans (1,2,3), il effectuera probablement simplement une analyse de table pour obtenir les ID Employee correspondants, car il est plus rapide de parcourir la table entière plutôt que d'y accéder. chaque branche de l’arborescence d’index et examinez les enregistrements individuellement.

SQL Server fait beaucoup de choses pour essayer d'optimiser l'exécution des requêtes.Cependant, il arrive parfois que l’on n’obtienne pas la bonne réponse.Si vous savez que SQL Server n'utilise pas l'index, en examinant le plan d'exécution dans l'analyseur de requêtes, vous pouvez indiquer au moteur de requête d'utiliser un index spécifique avec la modification suivante apportée à votre requête.

Select EmployeeId From Employee WITH (Index(Index_EmployeeTypeId )) Where EmployeeTypeId IN (1,2,3)

En supposant que l'index que vous avez sur le champ EmployeeTypeId est nommé Index_EmployeeTypeId.

Autres conseils

Habituellement, ce serait le cas, à moins que la clause IN ne couvre une trop grande partie de la table, et elle effectuerait alors une analyse de la table.La meilleure façon de le savoir dans votre cas spécifique serait de l'exécuter dans l'analyseur de requêtes et de consulter le plan d'exécution.

À moins que la technologie ne se soit améliorée d'une manière que je ne peux pas imaginer ces derniers temps, la requête "IN" affichée produira un résultat qui est effectivement l'opération OU de trois jeux de résultats, un pour chacune des valeurs de la liste "IN".La clause IN devient une condition d'égalité pour chacune des listes et utilisera un index le cas échéant.Dans le cas d'identifiants uniques et d'une table suffisamment grande, je m'attendrais à ce que l'optimiseur utilise un index.

Cependant, si les éléments de la liste ne sont pas uniques et que je suppose dans l'exemple qu'un "TypeId" est une clé étrangère, alors je suis plus intéressé par la distribution.Je me demande si l'optimiseur vérifiera les statistiques pour chaque valeur de la liste ?Supposons qu'il vérifie la première valeur et constate qu'elle se trouve dans 20 % des lignes (d'un tableau suffisamment grand pour avoir de l'importance).Il s'agira probablement d'une analyse de table.Mais le même plan de requête sera-t-il utilisé pour les deux autres, même s’ils sont uniques ?

C'est probablement sans objet - quelque chose comme une table Employee est susceptible d'être suffisamment petite pour rester mise en cache en mémoire et vous ne remarquerez probablement pas de différence entre cela et la récupération indexée de toute façon.

Et enfin, pendant que je prêche, méfiez-vous de la requête dans la clause IN :c'est souvent un moyen rapide de faire fonctionner quelque chose et (pour moi du moins) peut être un bon moyen d'exprimer l'exigence, mais il est presque toujours préférable de le reformuler sous forme de jointure.Votre optimiseur est peut-être suffisamment intelligent pour détecter cela, mais là encore, ce n'est peut-être pas le cas.Si vous ne contrôlez pas actuellement les performances par rapport aux volumes de données de production, faites-le : à l'heure de l'optimisation basée sur les coûts, vous ne pouvez pas être certain du plan de requête tant que vous n'avez pas une charge complète et des statistiques représentatives.Si vous n'y parvenez pas, préparez-vous à des surprises lors de la production...

Il y a donc le potentiel pour une clause "in" pour exécuter une analyse de table, mais l'Optimiseur essaiera de trouver la meilleure façon de le gérer?

L'utilisation ou non d'un index ne dépend pas tant du type de requête que du type et de la distribution des données dans la ou des tables, de la mise à jour des statistiques de votre table et du type de données réel de la colonne. .

Les autres affiches ont raison de dire qu'un index sera utilisé sur une analyse de table si :

  • La requête n'accédera pas à plus d'un certain pourcentage des lignes indexées (disons ~ 10 %, mais devrait varier selon les SGBD).
  • Alternativement, s'il y a beaucoup de lignes, mais relativement peu de valeurs uniques dans la colonne, il peut également être plus rapide d'effectuer une analyse de table.

L'autre variable qui n'est peut-être pas si évidente est de s'assurer que les types de données des valeurs comparées sont les mêmes.Dans PostgreSQL, je ne pense pas que les index seront utilisés si vous filtrez sur un float mais votre colonne est composée d'entiers.Il existe également certains opérateurs qui ne prennent pas en charge l'utilisation des index (encore une fois, dans PostgreSQL, l'opérateur ILIKE ressemble à ceci).

Comme indiqué cependant, vérifiez toujours l'analyseur de requêtes en cas de doute et la documentation de votre SGBD est votre amie.

@Mike:Merci pour l'analyse détaillée.Il y a certainement des points intéressants que vous soulevez là.L'exemple que j'ai posté est quelque peu trivial mais la base de la question vient de l'utilisation de NHibernate.

Avec NHibernate, vous pouvez écrire une clause comme celle-ci :

int[] employeeIds = new int[]{1, 5, 23463, 32523};
NHibernateSession.CreateCriteria(typeof(Employee))
.Add(Restrictions.InG("EmployeeId",employeeIds))

NHibernate génère ensuite une requête qui ressemble à

select * from employee where employeeid in (1, 5, 23463, 32523)

Ainsi, comme vous et d'autres l'avez souligné, il semble qu'il y aura des moments où un index sera utilisé ou une analyse de table aura lieu, mais vous ne pouvez pas vraiment le déterminer avant l'exécution.

Select EmployeeId From Employee USE(INDEX(EmployeeTypeId))

Cette requête effectuera une recherche à l'aide de l'index que vous avez créé.Ça marche pour moi.S'il vous plaît, essayez..

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top