I have a blacklist of people that should never be contacted. When I want to see if a person is in this list, I do the following:
-- Query 1
SELECT *
FROM bldb.dbo.blacklist l
WHERE l.matchcode
= dbo.fn_matchcode('12345','Sesame Street','1','Eddie','Bert')
The query runs very fast, since there is an index on matchcode column, and fn_matchcode is deterministic.
Think of matchcode as a compressed form of address and name, which helps me not to be affected from typos in street names etc. It consists of 22 chars: 13 for the address, 9 for the name. When I want to see if any person in 1 Sesame Street, 12345 is in blacklist, I do the following:
-- Query 2
SELECT *
FROM bldb.dbo.blacklist l
WHERE LEFT(l.matchcode,13)
= LEFT(dbo.fn_matchcode('12345','Sesame Street','1','Eddie','Bert'),13)
This runs extremely long...
On the contrary, this runs much faster:
-- Query 3
SELECT *
FROM bldb.dbo.blacklist l
WHERE LEFT(l.matchcode,13)
= (SELECT LEFT(dbo.fn_matchcode('12345','Sesame Street','1','Eddie','Bert'),13))
That means, the right hand side of the where condition gets calculated for every row! But why? The UDF is deterministic. Is it LEFT(), which is not deterministic?
EDIT:
The answers so far claimed that it is because the index does not get used. However, it is still not clear to me why the following happens.
When I write the query like this:
-- Query 4
SELECT *
FROM bldb.dbo.blacklist
WHERE matchcode LIKE LEFT(dbo.fn_matchcode('12345','Sesame Street','1','Eddie','Bert'),13) + '%'
it still takes several minutes to finish. Please note that the fn_matchcode just does some string manipulation and returns instantly.
When I hardcode the result of fn_matchcode into the query:
-- Query 5
SELECT *
FROM bldb.dbo.blacklist
WHERE matchcode LIKE '12345SSMSTRT1%'
it takes a couple of milliseconds! How would you explain that?