Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 SQL Server Administration (2005)
 Execution Plan

Author  Topic 

Kwisatz
Starting Member

14 Posts

Posted - 2009-07-13 : 06:12:41
Hi all - I am looking into a poorly performing stored procedure and found a RID lookup taking up %55 of the process. I am having problems however translating this back to the code in the procedure which is performing badly. I have attached a picture of the RID properties and also the code is below.

If anyone can help me understand how to identify the badly written code I would be grateful.

Thanks



SELECT
[S].[Acronym] AS StudyAcronym
, [O].[Name] AS OrganisationName
, ( CASE WHEN [I].[LastName] IS NULL THEN [I].[FirstName]
WHEN [I].[FirstName] IS NULL THEN [I].[LastName]
ELSE [I].[LastName] + ', ' + [I].[FirstName]
END ) AS InvestigatorName
, [AcS].[SiteName] AS AccrualSiteName
, [m].[StudyEntryYear]
, [m].[StudyEntryMonth]
, ISNULL([AccrualFigures].[Accrual], 0) AS Accrual
FROM
(
-- This subquery gets details of all investigators to feature in this report, irrespective of whether they have any accrual for the chosen year.
SELECT DISTINCT
[ABI].[StudyId]
, [ABI].[InvestigatorId]
, [ABI].[AccrualSiteId]
, [ABI].[OrganisationId]
FROM
ukcrn_reporting.dbo.AccrualByInvestigator ABI
INNER JOIN @studyInvestigators SI ON ( [ABI].[StudyId] = [SI].[StudyId]
AND [ABI].[InvestigatorId] = [SI].[InvestigatorId]
AND [ABI].[AccrualSiteId] = [SI].[AccrualSiteID]
)
INNER JOIN @Studies S ON [ABI].[StudyId] = [S].[StudyId]
INNER JOIN @Lrns L ON [ABI].[OrganisationId] = [L].[LrnId]
WHERE
[ABI].[TopicId] = @topicId
OR @topicID = -1
) AllInvestigators
CROSS JOIN @months m
LEFT OUTER JOIN (
-- This subquery gets details of investigators who have actually recruited during the year
SELECT
[ABI].[StudyId]
, [ABI].[InvestigatorId]
, [ABI].[AccrualSiteId]
, [ABI].[OrganisationId]
, DATEPART(yy, [ABI].[StudyEntryDate]) StudyEntryYear
, DATEPART(mm, [ABI].[StudyEntryDate]) StudyEntryMonth
, COUNT(*) AS Accrual
FROM
ukcrn_reporting.dbo.AccrualByInvestigator ABI
INNER JOIN @Studies S ON [ABI].[StudyId] = [S].[StudyId]
INNER JOIN @lrns L ON [ABI].[OrganisationId] = [L].[LrnId]
INNER JOIN @studyInvestigators SI ON ( [ABI].[StudyId] = [SI].[StudyId]
AND [ABI].[InvestigatorId] = [SI].[InvestigatorId]
AND [ABI].[AccrualSiteId] = [SI].[AccrualSiteID]
)
INNER JOIN @recruitTypes RT ON [ABI].[RecruitType] = [RT].[RecruitTypeId]
WHERE
[ABI].[StudyEntryDate] BETWEEN @DateFrom AND @DateTo
AND ( [ABI].[TopicId] = @TopicID
OR @TopicID = -1
)
GROUP BY
[ABI].[StudyId]
, [ABI].[InvestigatorId]
, [ABI].[AccrualSiteId]
, [ABI].[OrganisationId]
, DATEPART(yy, [ABI].[StudyEntryDate])
, DATEPART(mm, [ABI].[StudyEntryDate])
) AccrualFigures ON ( [AllInvestigators].[StudyId] = [AccrualFigures].[StudyId]
AND [AllInvestigators].[InvestigatorId] = [AccrualFigures].[InvestigatorId]
AND [AllInvestigators].[AccrualSiteId] = [AccrualFigures].[AccrualSiteId]
AND [AllInvestigators].[OrganisationId] = [AccrualFigures].[OrganisationId]
AND [m].[StudyEntryYear] = [AccrualFigures].[StudyEntryYear]
AND [m].[StudyEntryMonth] = [AccrualFigures].[StudyEntryMonth]
)
INNER JOIN [dbo].[Study] S ON [AllInvestigators].[StudyId] = [S].[Id]
INNER JOIN [dbo].[Investigator] I ON [AllInvestigators].[InvestigatorId] = [I].[Id]
INNER JOIN [dbo].[Organisation] O ON [AllInvestigators].[OrganisationId] = [O].[Id]
INNER JOIN [dbo].[AccrualSite] AcS ON [AllInvestigators].[AccrualSiteId] = [AcS].[Id]
ORDER BY
[S].[Acronym]
, [O].[Name]
, [AcS].[SiteName]

ahmad.osama
Posting Yak Master

183 Posts

Posted - 2009-07-14 : 03:19:25
well.... a rid lookup is like a bookmark look up on a heap..how ever it is done on a table with clustered index..this tell you that tho an index seek was done but all the data columns were not present in the index.

It does effect the I/O..however in your case only 1 row is returned...If u want to remove the rid lookup then consider creating a covering index for the columns listed in the execution plan attached.

hope this helps....
Go to Top of Page

Kwisatz
Starting Member

14 Posts

Posted - 2009-07-15 : 10:37:54
Hi thanks for the reply, I have played about with covering indexes and I can see a performance gain. Thanks.
Go to Top of Page

RickD
Slow But Sure Yak Herding Master

3608 Posts

Posted - 2009-07-15 : 10:52:11
You might want to look at INCLUDE to create a covering index instead of adding all the columns into one big index.
Go to Top of Page

Kwisatz
Starting Member

14 Posts

Posted - 2009-07-15 : 11:06:23
WIll do , in this case there are only 5 columns so should be ok I guess?
Go to Top of Page

ahmad.osama
Posting Yak Master

183 Posts

Posted - 2009-07-15 : 12:58:02
quote:
Originally posted by Kwisatz

WIll do , in this case there are only 5 columns so should be ok I guess?



nopes...include option is a better one to create a covering index.......
thou the included columns contribute to the size of the index but they are excluded when calculating the index key size which is of 900 bytes.....you can find out more info in BOL
Go to Top of Page
   

- Advertisement -