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.
@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
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. –
Une question: comment les lignes peuvent-elles être présentes dans la table de base? – gbn