Comment rendre une vue syndicale plus efficace?

8

J'ai une grande table (des dizaines à des centaines de millions d'enregistrements) que nous avons divisée pour des raisons de performances en tables actives et archivées, en utilisant un mappage de champ direct et en exécutant un processus d'archivage tous les soirs.

À plusieurs endroits de notre code, nous devons exécuter des requêtes qui combinent les tables actives et d'archivage, presque invariablement filtrées par un ou plusieurs champs (sur lesquels nous avons évidemment mis des index dans les deux tables). Pour plus de commodité, il serait logique d'avoir une vue comme celle-ci:

create view vMyTable_Combined as
select * from MyTable_Active
union all
select * from MyTable_Archive

Mais si je lance une requête comme

select * from vMyTable_Combined where IndexedField = @val

il va faire l'union sur tout depuis Active et Store avant le filtrage @val, ce qui va tuer les performances.

Existe-t-il un moyen intelligent de faire en sorte que les deux sous-requêtes de l'union voient chaque filtre @valavant de créer l'union?

Ou peut-être y a-t-il une autre approche que vous suggéreriez pour atteindre mon objectif, c'est-à-dire un moyen simple et efficace d'obtenir le jeu d'enregistrements d'union, filtré par le champ indexé?

EDIT: voici le plan d'exécution (et vous pouvez voir les vrais noms de table ici):

plan d'exécution

Curieusement, la table active utilise en fait l'index correct (plus une recherche RID?) Mais la table d'archive fait un scan de table!

Shaul Behr
la source
Les commentaires ne sont pas pour une discussion approfondie; cette conversation a été déplacée vers le chat .
Paul White 9

Réponses:

8

Les commentaires sur la question montrent que le problème est que la base de données de test que l'OP utilisait pour développer la requête avait des caractéristiques de données radicalement différentes de la base de données de production. Il avait beaucoup moins de lignes et le champ utilisé pour le filtrage n'était pas suffisamment sélectif.

Lorsque le nombre de valeurs distinctes dans une colonne est trop petit, l'indice peut ne pas être suffisamment sélectif. Dans ce cas, un balayage de table séquentiel est moins cher qu'une opération de recherche d'index / de ligne. En règle générale, une analyse de table utilise intensivement les E / S séquentielles, ce qui est beaucoup plus rapide que les lectures à accès aléatoire.

Souvent, si une requête renvoie plus de seulement quelques pour cent de lignes, il sera moins cher de faire un scan de table qu'une recherche d'index / ligne ou une opération similaire qui fait un usage intensif d'E / S aléatoires.

ConcernedOfTunbridgeWells
la source
1

Juste pour ajouter, ce que j'ai trouvé. Si tu fais:

create view vMyTable_Combined as
select *, 1 AS [Active] from MyTable_Active
union all
select *, 0 AS [Active] from MyTable_Archive

Vous pouvez ensuite filtrer sur le champ [Actif] et vous assurer que l'autre partie n'est pas chargée.

Michael Møldrup
la source