Pourquoi la requête SQL n'utilise-t-elle pas la key primaire pour SELECT lorsqu'elle est la plus appropriée?

Scénario (essaye de find une correspondance 1-1 pour mon scénario de production): Récupère la list de toutes les personnes qui ont voyagé avec Virgin Airlines ou Emirates de New York.

Table : tbl_Flyer a quelques colonnes contenant tous les détails sur les personnes qui ont volé à n'importe quel moment. La key primaire est CountryId, CityId, AirlineId, PersonId

Maintenant, une requête SQL simple ressemble à ceci:

 SELECT flyer.PersonId FROM tbl_Flyer passenger WHERE passenger.CountryId = @countryId AND passenger.City= @cityId AND passenger.AirlineId IN (SELECT values FROM @allAirlineIds) 

@countryId et @cityId et @allAirlineIds sont correctement envoyés à la procédure stockée SQL. Mon hypothèse serait que cette requête utiliserait la key primaire car toutes les 4 colonnes utilisées dans la requête sont présentes dans PK, mais pour une raison quelconque, ce n'est pas le cas.

Il utilise un index non cluster qui a été ajouté pour pouvoir interroger les passagers sur la database personnelles comme l'âge, le sexe. (ressemble à (CountryId, CityId, Age, Sexe))

J'ajoute un indice ForceSeek à la requête mais je veux comprendre s'il y a un anti-pattern que je pourrais utiliser ici? N'importe quelle idée pourquoi SQL défierait la logique et n'utiliserait pas le PK pour une search?

Le choix fait par votre moteur de database d'utiliser un index ou un autre est fait automatiquement basé sur des heuristiques automatisées … qui ne sont pas toujours les plus précises. (99% des fois, ils sont, mais parfois, le cerveau humain a trouvé un meilleur moyen). Ces heuristiques sont calculées sur la base de règles généralists, et parfois ne correspondent pas à la réalité du contenu de votre database (string colonne avec toujours la même première lettre, colonne avec beaucoup de null, …)

L'opération "Sélectionner dans" doit être effectuée pour chaque ligne de votre table, stockée et considérée comme extrêmement chère par la plupart des moteurs de database, de sorte que votre database peut utiliser d'une autre manière (index non clusterisé dans votre cas )

L'utilisation d'Exist dans est considérée comme beaucoup less chère, et rendra votre moteur de database plus susceptible de choisir l'index.

utilisez ForceSeek si ce n'est pas assez.

Vous pouvez également avoir le même problème si le type de CountryId, CityId, AirlineId, PersonId n'est pas le même que @CountryId, @CityId, @AirlineId, @PersonId (la conversion de type est chère)