SELECT DISTINCT dbo.ufn_GetuserEmailId(hrb.UserID)
,''
,''
,0
,hrb.RID
,0
,'Photon Registration'
,(
CASE
WHEN hrb.SourceID = 51
THEN 10655 /*10517*/
WHEN hrb.SourceGroupID = 1
THEN 10518
WHEN hrb.SourceID = 4
THEN 10656 /*10519*/
WHEN hrb.SourceID = 1
THEN 10657 /*10520*/
END
)
,GETUTCDATE()
,hrb.UserID
,0
FROM HC_RESUME_BANK hrb WITH (NOLOCK)
INNER JOIN HC_USER_MAIN hum WITH (NOLOCK) ON hrb.UserID = hum.RID
WHERE (
hrb.SourceID IN (
51
,1
)
OR (hrb.SourceGroupID = 1)
OR (
hrb.SourceID = 4
AND isnull(hrb.SourceEmailId, '') <> ''
AND hrb.SourceEmailId NOT LIKE '%integra%'
)
)
AND hrb.SourceID <> 10647
AND DATEDIFF(MI, hrb.CreatedDate, GETUTCDATE()) <= 5
-
2It helps with performance tuning questions if you post the execution plan, that will highlight the bottlenecks in query, you are probably right about the `DATEDIFF` but the execution plan means we do not have to guess. Indexes are going to be the next level of optimisation, again execution plan will tell you what indexes are being used and what types of indexes might help. – Chris Schaller Mar 02 '22 at 13:27
-
2Why the `WITH (NOLOCK)`? You do know what dirty reads mean? Why the join to HC_USER_MAIN? Is this to ensure that the userid exists in the table? What makes the costly `DISTINCT` necessary? Why are there duplicates you must eliminate? Why do you need a function to get a user's email ID? Can't you read it from a user table? It may help a lot, if you describre what the tables represent and what their unique keys are. And then describe what task the query shall solve. Sample data may help, too. – Thorsten Kettner Mar 02 '22 at 13:36
-
1WITH (NOLOCK) is often faster. It is not considered a best practice, but in some shops it is used consistently for performance, as it is an engineering trade-off. – JosephDoggie Mar 02 '22 at 13:43
-
1@JosephDoggie At the expense of incorrect information or runtime execution errors. It is more than just an "engineering" tradeoff and rarely is the usage intentionally evaluated as such. – SMor Mar 02 '22 at 13:48
-
I've never personally seen NOLOCK cause a runtime execution error. I suppose anything is possible, though. – JosephDoggie Mar 02 '22 at 14:01
1 Answers
When filtering by a time difference compared to now you can pre-compute the lower bound date and use a simple greater than comparison which is much more efficient than evaluating a function for each record. We move the function evaluation outside of the query so that SQL so we only evaluate it once.
This trick changes the comparison such that you could do a direct lookup in an index, a function evaluations cannot do this.
Instead of:
WHERE ... DATEDIFF(MI, hrb.CreatedDate, GETUTCDATE()) <= 5
Which translates to "Created in the last 5 minutes", we can calculate the timestamp 5 minutes ago and use that:
DECLARE @minDate DateTime = (SELECT DATEADD(MI, -5, GETUTCDATE()))
...
WHERE ... hrb.CreatedDate >= @minDate
Putting that all together:
DECLARE @minDate DateTime = (SELECT DATEADD(MI, -5, GETUTCDATE()));
SELECT DISTINCT dbo.ufn_GetuserEmailId(hrb.UserID)
,''
,''
,0
,hrb.RID
,0
,'Photon Registration'
,(
CASE
WHEN hrb.SourceID = 51
THEN 10655 /*10517*/
WHEN hrb.SourceGroupID = 1
THEN 10518
WHEN hrb.SourceID = 4
THEN 10656 /*10519*/
WHEN hrb.SourceID = 1
THEN 10657 /*10520*/
END
)
,GETUTCDATE()
,hrb.UserID
,0
FROM HC_RESUME_BANK hrb WITH (NOLOCK)
INNER JOIN HC_USER_MAIN hum WITH (NOLOCK) ON hrb.UserID = hum.RID
WHERE (
hrb.SourceID IN (
51
,1
)
OR (hrb.SourceGroupID = 1)
OR (
hrb.SourceID = 4
AND isnull(hrb.SourceEmailId, '') <> ''
AND hrb.SourceEmailId NOT LIKE '%integra%'
)
)
AND hrb.SourceID <> 10647
AND hrb.CreatedDate >= @minDate
Performance should be increased instantly, but if you create an index on hrb.CreatedDate
you might see even better performance gains.
Update
Please note that the use of DISTINCT
will also have a significant impact on performance. If there really is a possibility of duplication then we usually advise to re-write the query so that there is no longer any duplication.
In this case you are joining on HC_USER_MAIN
but are not querying any fields from that table, so we have to assume you are doing this for filtering purposes only. If the relationship with HC_USER_MAIN
is 1:1 then I do not see any reason for the DISTINCT
at all. If removing the DISTINCT
clause does result in duplications then try to refactor out the join and change that to a lookup or WHERE IN
correlation so that it doesn't affect the results.
Regarding NOLOCK
In response to comments NOLOCK
here will only improve performance, at the risk of returning inconsistent results, but removing NOLOCK
is only going to make this query slower. Yes the use of this hint should be challenged, but in many high frequency queries that poll a changing table, so very much like this one, it is common and usually appropriate to use the NOLOCK
hint.
There is a good discussion here Is the NOLOCK (Sql Server hint) bad practice? but from a pure performance point of view, OP should leave it in.

- 13,704
- 3
- 43
- 81
-
2I would also suggest that the `NOLOCK`s and the `DISTINCT` should not be there. The latter is a very expensive operator; especially against 11 columns. – Thom A Mar 02 '22 at 13:47
-
1And that is why we really need to see the query execution plan. `NOLOCK` is probably helpful here if the query does take some time to execute and this table has a high frequency of updates, too much speculation... distinct also might be necessary if the result ends up with duplicate rows, its just too much speculation to include it in a solution, but they are very valid points worth reviewing. – Chris Schaller Mar 02 '22 at 13:59
-
Yes, but all the OP has done is make a code dump; if we need more information, then you shouldn't be answering yet. Instead add comments to the question to clarify what's needed. A code dump with a plea to the male members of the community in the title a question does not make. – Thom A Mar 02 '22 at 14:06
-
We don't need any additional information, with `NOLOCK` and `DISTINCT` we have to assume OP knows what they are doing. The date logic change will have such a significant impact on this that we don't need to talk about any other issues. That is what I was getting at, thanks for bringing it up, but it is a secondary issue to an underlying flaw in the original query – Chris Schaller Mar 02 '22 at 14:22
-
I've updated my post with my stance on `DISTINCT` and `NOLOCK`. Yes it is a bandaid, but if you experience heavy traffic on your tables, it can really help keep things running efficiently. – Chris Schaller Mar 02 '22 at 14:41
-
*"we have to assume OP knows what they are doing"* honestly, I also assume the person has no idea what they are doing when using `NOLOCK`; experience has taught me that far too many people (ab)use it. – Thom A Mar 02 '22 at 14:56
-
But in this case, having `NOLOCK` will only _help_ performance, so as not to confuse OP or other readers we just don't talk about it. I can't stress enough, in this type of query `NOLOCK` is not just acceptable, it is even expected. – Chris Schaller Mar 02 '22 at 15:15
-
Note - you can do `hrb.CreatedDate >= DATEADD(MI, -5, GETUTCDATE())` directly. The optimizer is smart enough to know that that's a constant and will evaluate it once (as opposed to once for every row). Also, you avoid some shenanigans with the optimizer being dumb about local variables. – Ben Thul Mar 02 '22 at 16:47