• 1) Maybe you can combine the three separate UPDATEs into one, as shown below, avoiding repeated joins of the same tables.

    2) Depending on the row counts, you might consider creating a filtered index on IBC.ProcessedFlag, including at least InstanceId and SiteId (if they are the clustering keys, of course you won't need to explicitly INCLUDE them, although it doesn't hurt anything to do so).

    3) Beyond just this query, if you most often access the listed tables by InstanceId and SiteId, then if possible cluster the tables that way. That should speed up all your processing.

    I don't know enough about the data distributions to know whether it should be ( InstanceId, SiteId ) or ( SiteId, InstanceId ), but you can determine that. If the third column is consistently specified in the WHERE, you could specify it in the clus key as well if you want; that is: ( key1, key2, LocalBuildingId | LocalEmployeeId | NoteCategoryCode ), although that lengthens the key so much that it must be weighed carefully.

    Update IBC

    SET IBC.ProcessedFlag = 1,

    IBC.ReturnCode = '2001',

    IBC.EmailSentFlag = 0,

    IBC.ProcessedDate = GETDATE()

    FROM InBound_BuildingNote IBC WITH(NOLOCK)

    LEFT JOIN Building B WITH(NOLOCK) ON B.InstanceId = IBC.InstanceId

    AND B.SiteId = IBC.SiteId

    AND B.LocalBuildingId = IBC.LocalBuildingId

    LEFT JOIN Employee E WITH(NOLOCK) ON E.InstanceId = IBC.InstanceId

    AND E.SiteId = IBC.SiteId

    AND E.LocalEmployeeId = IBC.LocalEmployeeId

    LEFT JOIN NoteCategory NC ON NC.NoteCategoryCode = IBC.NoteCategoryCode

    AND NC.InstanceId = IBC.InstanceId

    AND NC.SiteId = IBC.SiteId

    WHERE (B.LocalBuildingId IS NULL OR E.LocalEmployeeId IS NULL OR NC.NoteCategoryCode IS NULL)

    AND IBC.ProcessedFlag = 0

    AND IBC.InstanceId = @InstanceID

    AND IBC.SiteId = @SiteID

    SQL DBA,SQL Server MVP(07, 08, 09) A socialist is someone who will give you the shirt off *someone else's* back.