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 @val
avant 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):
Curieusement, la table active utilise en fait l'index correct (plus une recherche RID?) Mais la table d'archive fait un scan de table!
la source
Réponses:
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.
la source
Juste pour ajouter, ce que j'ai trouvé. Si tu fais:
Vous pouvez ensuite filtrer sur le champ [Actif] et vous assurer que l'autre partie n'est pas chargée.
la source