2010-10-01 4 views
1

C'est difficile à expliquer, mais je vais essayer. query plan picPlan de requête CTE pour une requête complexe - triple exécution de la même requête init - pourquoi?

Comme vous le voyez sur query_plan photo ci-jointe (Il est plan de requête pour « Tout en un » requête décrit ci-dessous), il y a 3 presque les mêmes « blocs » - ma question est pourquoi? Il me semble que quand j'ai "tout en un" (voir ci-dessous) requête le bloc "Init" (qui est plutôt lourd) est exécuté trois fois avec des filtres différents au lieu d'être SPOOLED et réutilisé plus tard.

Ce temps d'exécution de requête est d'environ 45 secondes. Il requête pourrait être présentée sous une forme:

-- Complex "All in One place" Query 
WITH init as (
    Init1 complex query here -- (10 sec to run) if executed alone 
) 
, step1 as (select * from init .. joins... where ... etc), 
step2 as (select *, row_number() over(__condition__) as rn from step1 where _filter1_) 
, step3 as (select * from step2 where __filter2_), 
.... some more steps could be here .... 
select * 
into target_table 
from step_N; 
-- 45sec CPU time 

L'important est ici que j'utilise les Step1, Etape 2, ..., tables Stepn dans « AVEC » clause séquentielle - Étape 1 utilise la table INIT, donc Step2 utilise la table Step1, Step3 utilise Step2 Table etc. J'ai besoin de cela en raison des différents classements que je traite après chaque étape qui est utilisée plus tard pour le filtrage.

Si le changement cette requête CTE complexe (je mets le résultat de Init requête dans la table, le processus puis d'autres étapes sans changement):

-- Complex query separated from the rest of the query 
with Init as ( 
    The same Init1 complex query here 
) 
select * 
into test_init 
from init; 
-- 10sec CPU time 

with step1 as (select * from test_init .. joins... where ... etc), 
step2 as (select *, row_number() over(__condition__) as rn from step1 where _filter1_) , 
step3 as (select * from step2 where __filter2_), 
.... some more steps could be here .... 
select * 
into target_table 
from step_N; 
-- 5sec CPU time 

J'ai obtenu environ 15 s de temps exec, qui semble OK pour moi. Parce que 10sec est la première requête complexe qui est difficile à améliorer.

Par conséquent, je ne peux pas obtenir ce comportement MS Sql Server 2005? Quelqu'un pourrait-il m'expliquer cela? C'est plutôt intéressant, je suppose!

Répondre

1

On dirait que l'optimiseur pense qu'il serait plus rapide d'exécuter la requête trois fois avec des conditions différentes. L'optimiseur n'a pas toujours raison.

Il est en fait assez courant d'utiliser une table temporaire pour forcer SQL Server à effectuer toute la requête complexe en premier. Habituellement, vous utiliseriez une table temporaire au lieu de test_init:

insert into #temptbl select * from Init 

Une table temporaire est également utilisée par SQL Server pour stocker les résultats des jointures et des sous-requêtes. L'utilisation d'une table temporaire n'a pas d'impact négatif sur les performances.

+0

Nous utilisons des tables parfois à des fins d'assurance qualité ultérieurement. Les tables de température sont utilisées le cas échéant. Hmmm ... Y a-t-il un moyen de "dire" à MS SQL qu'il vaut mieux mettre le résultat dans le spool et le réutiliser? Écrire un plan, des conseils, quelque chose? – zmische

+0

@zmische - Cela pourrait bien être possible avec des conseils de plan, mais rappelez-vous que la bobine sera juste une table de travail dans tempdb de toute façon. –

+0

Oui, vous avez raison. Mais je suis à propos de faire le travail dans une requête, sans sélection supplémentaire .. dans. Encore plus si c'est la même chose du point de vue du serveur MS SQL. %) Thx quand même! – zmische