Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8191153
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 7, 20262026-06-07T03:51:24+00:00 2026-06-07T03:51:24+00:00

I’m trying to optimise a stored procedure and after looking at the execution plan

  • 0

I’m trying to optimise a stored procedure and after looking at the execution plan and execution times I’m surprised by the results. Can anyone explain them.

The original SQL I wrote has 2 almost identical selects that I then pull together in a CTE, I tried to refactor that so the main work was done once, populating a table variable so I could then have 2 smaller selects that filtered the data the way I needed. The sole difference between the 2 select statements is the value that’s passed to TVF_GetChildGroups in the 1st select @AreaID represents the area of reporting for the current context and in the 2nd select @RootReportLevelID is simply all areas. So it’s the peers of the user context and the aim is to allow comparison between your scores and the average of everyone else.

DECLARE @Scores TABLE
(
  ShortName VARCHAR(50) ,
  PCTMax INT ,
  PCTAvg INT ,
  PCTMin INT ,
  ALLAvg INT ,
  AllMax INT ,
  AllMin INT
)
INSERT  INTO @Scores
    SELECT  T2.ShortName ,
            MAX(T1.MeridianScore) AS PCTMax ,
            CAST(( CAST(SUM(T1.contribution) AS DECIMAL) / CAST(SUM(T1.maxvalue) AS DECIMAL) * 100 ) AS DECIMAL(5, 2)) AS PCTAvg ,
            MIN(T1.MeridianScore) AS PCTMin ,
            CAST(( CAST(SUM(T2.contribution) AS DECIMAL) / CAST(SUM(T2.maxvalue) AS DECIMAL) * 100 ) AS DECIMAL(5, 2)) AS AllAvg ,
            MAX(T2.MeridianScore) AS AllUpperScore ,
            MIN(T2.MeridianScore) AS AllLowerScore
    FROM    ( SELECT    US.PKID ,
                        PT.ShortName ,
                        CAST(( CAST(SUM(RES.contribution) AS DECIMAL) / CAST(SUM(RES.maxvalue) AS DECIMAL) * 100 ) AS DECIMAL(5, 2)) AS MeridianScore ,
                        SUM(Contribution) AS Contribution ,
                        SUM(MaxValue) AS MaxValue
              FROM      tblUploadedScorecards AS US
                        INNER JOIN tblUploadedScoreCardResults AS RES ON US.PKID = RES.FKUploadedScoreCardID
                        INNER JOIN tblUploadedScorecardHeaders AS USH ON USH.FKUploadedScorecardID = US.PKID
                        INNER JOIN @ProviderTable AS PT ON USH.HeaderValue = PT.FullName
                        INNER JOIN TVF_GetChildGroups(@AreaID) AS TGCG ON TGCG.GroupName = US.Branch
              WHERE     US.FKScoreCardID = 185
                        AND reviewed = 1
                        AND ShopDate BETWEEN @StartDate AND @EndDate
                        AND RES.Rating <> 'I'
                        AND USH.FKScorecardHeaderID = 71
              GROUP BY  US.PKID ,
                        PT.ShortName ) AS T1
            RIGHT JOIN ( SELECT US.PKID ,
                                PT.ShortName ,
                                CAST(( CAST(SUM(RES.contribution) AS DECIMAL) / CAST(SUM(RES.maxvalue) AS DECIMAL) * 100 ) AS DECIMAL(5, 2)) AS MeridianScore ,
                                SUM(Contribution) AS Contribution ,
                                SUM(MaxValue) AS MaxValue
                         FROM   tblUploadedScorecards AS US
                                INNER JOIN tblUploadedScoreCardResults AS RES ON US.PKID = RES.FKUploadedScoreCardID
                                INNER JOIN tblUploadedScorecardHeaders AS USH ON USH.FKUploadedScorecardID = US.PKID
                                INNER JOIN @ProviderTable AS PT ON USH.HeaderValue = PT.FullName
                                INNER JOIN TVF_GetChildGroups(@RootReportLevelID) AS TGCG ON TGCG.GroupName = US.Branch
                         WHERE  US.FKScoreCardID = 185
                                AND reviewed = 1
                                AND ShopDate BETWEEN @StartDate AND @EndDate
                                AND RES.Rating <> 'I'
                                AND USH.FKScorecardHeaderID = 71
                         GROUP BY US.PKID ,
                                PT.ShortName ) AS T2 ON T1.ShortName = T2.ShortName
    GROUP BY T2.ShortName

So I refactored out the commonality into a table variable against which I could apply the join to the TVF later in the hopes of not needing to hit the tables so much and ended up with this:

DECLARE @PreHierarchyResults TABLE 
(
PKID INT ,
Branch VARCHAR(150) ,
ShortName VARCHAR(50) ,
Contribution DECIMAL(20,3),
MaxValue DECIMAL(20,3)
)

INSERT INTO @PreHierarchyResults
    ( PKID ,
      Branch ,
      ShortName ,
      Contribution ,
      MaxValue )
SELECT  US.PKID ,
    US.Branch ,
    PT.ShortName ,
    Contribution AS Contribution ,
    MaxValue AS MaxValue
FROM    tblUploadedScorecards AS US
    INNER JOIN tblUploadedScoreCardResults AS RES ON US.PKID = RES.FKUploadedScoreCardID
    INNER JOIN tblUploadedScorecardHeaders AS USH ON USH.FKUploadedScorecardID = US.PKID
    INNER JOIN @ProviderTable AS PT ON USH.HeaderValue = PT.FullName
WHERE   US.FKScoreCardID = 185
    AND reviewed = 1
    AND ShopDate BETWEEN @StartDate AND @EndDate
    AND RES.Rating <> 'I'
    AND USH.FKScorecardHeaderID = 71


INSERT  INTO @Scores
    SELECT  T2.ShortName ,
            MAX(T1.MeridianScore) AS PCTMax ,
            CAST(( CAST(SUM(T1.contribution) AS DECIMAL) / CAST(SUM(T1.maxvalue) AS DECIMAL) * 100 ) AS DECIMAL(5, 2)) AS PCTAvg ,
            MIN(T1.MeridianScore) AS PCTMin ,
            CAST(( CAST(SUM(T2.contribution) AS DECIMAL) / CAST(SUM(T2.maxvalue) AS DECIMAL) * 100 ) AS DECIMAL(5, 2)) AS AllAvg ,
            MAX(T2.MeridianScore) AS AllUpperScore ,
            MIN(T2.MeridianScore) AS AllLowerScore
    FROM    ( SELECT    PHR.PKID ,
                        ShortName ,
                        CAST(( CAST(SUM(contribution) AS DECIMAL) / CAST(SUM(maxvalue) AS DECIMAL) * 100 ) AS DECIMAL(5, 2)) AS MeridianScore ,
                        SUM(Contribution) AS Contribution ,
                        SUM(MaxValue) AS MaxValue
              FROM      @PreHierarchyResults AS PHR 
                        INNER JOIN TVF_GetChildGroups(@AreaID) AS TGCG ON TGCG.GroupName = PHR.Branch 
              GROUP BY PHR.PKID , ShortName) AS T1
            RIGHT JOIN ( SELECT PHR2.PKID ,
                                ShortName ,
                                CAST(( CAST(SUM(Contribution) AS DECIMAL) / CAST(SUM(Maxvalue) AS DECIMAL) * 100 ) AS DECIMAL(5, 2)) AS MeridianScore ,
                                SUM(Contribution) AS Contribution ,
                                SUM(MaxValue) AS MaxValue
                         FROM   @PreHierarchyResults AS PHR2
                                INNER JOIN TVF_GetChildGroups(@RootReportLevelID) AS TGCG ON TGCG.GroupName = PHR2.Branch 
                         GROUP BY PHR2.PKID , ShortName) AS T2 ON T1.ShortName = T2.ShortName
    GROUP BY T2.ShortName

For the original SQL I get execution times:

SQL Server Execution Times:
CPU time = 16 ms, elapsed time = 11 ms.
Table ‘#012F94F2’. Scan count 0, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘tblUploadedScoreCardResults’. Scan count 4456, logical reads 13943, physical reads 40, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘Worktable’. Scan count 6, logical reads 29800, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘tblUserGroups’. Scan count 2, logical reads 118, physical reads 1, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘tblUploadedScorecards’. Scan count 0, logical reads 29496, physical reads 8, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘tblUploadedScorecardHeaders’. Scan count 192, logical reads 746, physical reads 5, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘#7D5F040E’. Scan count 186, logical reads 372, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

and after the refactoring I get:

SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 10 ms.
Table ‘#48563EF2’. Scan count 0, logical reads 5106, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘tblUploadedScoreCardResults’. Scan count 185, logical reads 614, physical reads 41, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘tblUploadedScorecards’. Scan count 0, logical reads 370, physical reads 8, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘tblUploadedScorecardHeaders’. Scan count 7, logical reads 23, physical reads 5, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘#439189D5’. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(5059 row(s) affected)
(1 row(s) affected)

SQL Server Execution Times:
CPU time = 16 ms, elapsed time = 199 ms.
Table ‘#47621AB9’. Scan count 0, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘Worktable’. Scan count 114, logical reads 1770, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘tblUserGroups’. Scan count 112, logical reads 998, physical reads 1, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘#48563EF2’. Scan count 112, logical reads 5376, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Looking at the output I think it’s clear that the first version is more efficient, but I just don’t understand why it should be the case as it appears to hit 4 tables twice whereas in the 2nd version those tables are only hit the one time.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-07T03:51:25+00:00Added an answer on June 7, 2026 at 3:51 am

    I would also compare the actual execution plans between your original and revised queries.

    Also check the indexes on tblUploadedScorecards, tblUploadedScoreCardResults, and tblUploadedScorecardHeaders. After caching data from those tables into @PreHierarchyResults, you might be losing the benefits of some covering indexes on the join columns in your second query.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Does anyone know how can I replace this 2 symbol below from the string
I am trying to understand how to use SyndicationItem to display feed which is
Basically, what I'm trying to create is a page of div tags, each has
I'm new to using the Perl treebuilder module for HTML parsing and can't figure
link Im having trouble converting the html entites into html characters, (&# 8217;) i
For some reason, after submitting a string like this Jack’s Spindle from a text
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I am trying to render a haml file in a javascript response like so:
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
I'm trying to decode HTML entries from here NYTimes.com and I cannot figure out

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.