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?