2010-08-10 4 views
4

J'ai deux vues indexées, v_First et v_Second. Ces vues fonctionnent très bien lorsque j'ai une clause WHERE qui filtre uniquement en fonction de l'une de ces vues. Toutefois, dès que j'ai des critères de filtre basés sur les deux vues, j'obtiens deux analyses d'index en cluster et une performance médiocre.Pourquoi le serveur SQL n'utilise-t-il pas mon index? (Filtrage sur les vues indexées jointes)

Ma requête est:

SELECT * FROM dbo.v_First (NOEXPAND) 
JOIN dbo.v_Second (NOEXPAND) 
ON dbo.v_First.id = dbo.v_Second.id 
WHERE 
dbo.v_First.Firstname = 'JUSTIN' 
OR dbo.v_Second.Surname = 'JUSTIN' 

Si je commente sur l'un des deux ci-dessus WHERE clauses puis-je obtenir la requête et recherches effectue donc je sais que j'ai individuellement les bons index définis.

Pourquoi la requête ne fonctionne-t-elle pas lors du filtrage basé sur plusieurs vues indexées et que puis-je faire pour le résoudre?

(Désolé, je ne peux pas poster des plans d'exécution, ils sont insignifiants de toute façon - juste deux index scans d'index en cluster sur les deux points de vue respectifs regroupés et une jointure par fusion)

Mise à jour:

v_First colonnes:

  • ID (bigint, index cluster)
  • Prénom (varchar (254), nonclus tered index)

v_Second colonnes:

  • ID (bigint, index en cluster)
  • nom (varchar (254), l'index non-cluster)

Tous les indices ne contient que la seule colonne.

mise à jour, la seconde:

J'ai trouvé que si la clause OR est remplacée par une clause AND, la requête exécute bien. Je l'ai aussi trouvé que si je change la requête à utiliser une instruction UNION au lieu d'une OR la requête effectue bien:

SELECT * FROM dbo.v_First (NOEXPAND) 
JOIN dbo.v_Second (NOEXPAND) 
ON dbo.v_First.ID = dbo.v_Second.ID 
WHERE dbo.v_First.Firstname = 'JUSTIN' 
UNION SELECT * FROM dbo.v_First (NOEXPAND) 
JOIN dbo.v_Second (NOEXPAND) 
ON dbo.v_First.ID = dbo.v_Second.ID 
WHERE dbo.v_Second.Surname = 'JUSTIN' 

Pour autant que je suis au courant de ces deux questions devraient être équivalentes?

Enfin, je l'ai aussi trouvé que l'utilisation d'un sous-requête au lieu a aussi un effet bizarre, la requête suivante effectue bien:

SELECT * FROM dbo.v_First (NOEXPAND) 
-- JOIN dbo.v_Second (NOEXPAND) 
-- ON dbo.v_First.ID = dbo.v_Second.ID 
WHERE dbo.v_First.ID IN 
(
     SELECT ID FROM dbo.v_Second (NOEXPAND) 
     WHERE dbo.v_Second.Surname = 'JUSTIN' 
) 
OR dbo.v_First.Firstname = 'JUSTIN' 

Toutefois, si je le décommenter JOIN (pour que je puisse obtenir les colonnes de la deuxième table dans les résultats de ma requête) puis j'obtiens un scan de table sur l'index clusterisé v_Second (notez toutefois que c'est encore mieux que la requête d'origine car elle implique seulement 1 scan, au lieu de 2).

Je suis très confus - que se passe-t-il?Il semble que je puisse contourner ces problèmes en «refactorisant» ma requête, mais je crains de ne pas comprendre ce qui se passe ici - je préfère éviter de faire des changements que je ne comprends pas complètement.

+0

@OMG - Presque uniquement les colonnes et les index qui sont absolument nécessaires pour créer une vue indexée - J'ai mis à jour ma question. – Justin

+0

Même avec une table avec juste ID, prénom, nom de famille, regroupés sur l'ID et indexés sur Prénom et Nom de famille séparément, une auto-jointure dans les lignes de votre requête aboutit à un plan de requête "mauvais" similaire + exécution lente. L'introduction d'une seconde table avec le même schéma que le premier et les mêmes index n'améliore pas la requête. Intéressant. –

+0

Une question: comment les lignes peuvent-elles être présentes dans la table de base? – gbn

Répondre

3

Observations

  • Vous avez un "OU" condition qui ne sargable

  • Vous devrez peut-être ajouter ID à chaque index de sorte qu'il est disponible sans scans/lookups

  • I J'aimerais bien voir les plans de toute façon. Utilisez SET SHOWPLAN_TEXT

Pour répondre à votre question, j'aurais probablement un index sur la table de base avec les deux colonnes de texte et laissez-le scanner que. L'OR ne vous donne pas beaucoup d'options et 2 vues indexées est inutile à mon humble avis. Après votre mise à jour, vous avez quelques constructions SQL artificielles: avez-vous vraiment besoin de 2 vues indexées et d'une table dérivée fantaisie ou UNION?

+0

Les vues indexées doivent contourner certaines limitations des tables de base - c'est très étrange et loin d'être idéal - j'étudie les vues indexées comme une approche de moins de deux maux. – Justin

Questions connexes