У меня есть черный список людей, с которыми никогда не следует связываться. Когда я хочу увидеть, есть ли человек в этом списке, я делаю следующее:
-- Query 1
SELECT *
FROM bldb.dbo.blacklist l
WHERE l.matchcode
= dbo.fn_matchcode('12345','Sesame Street','1','Eddie','Bert')
Запрос выполняется очень быстро, поскольку в столбце кода совпадения есть индекс, а fn_matchcode
является детерминированным.
Думайте о коде поиска как о сжатой форме адреса и названия, которая помогает мне не подвергаться влиянию опечаток в названиях улиц и т. Д. Он состоит из 22 символов: 13 для адреса, 9 для названия. Когда я хочу посмотреть, есть ли кто-нибудь на 1 Улица Сезам, 12345 в черном списке, я делаю следующее:
-- Query 2
SELECT *
FROM bldb.dbo.blacklist l
WHERE LEFT(l.matchcode,13)
= LEFT(dbo.fn_matchcode('12345','Sesame Street','1','Eddie','Bert'),13)
Это работает очень долго ...
Наоборот, это работает намного быстрее:
-- 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))
Это означает, что правая часть условия where вычисляется для каждой строки! Но почему? UDF является детерминированным. Это LEFT()
, которое не является детерминированным?
EDIT:
Ответы до сих пор утверждали, что это потому, что индекс не используется. Однако мне все еще не ясно, почему происходит следующее.
Когда я пишу запрос так:
-- Query 4
SELECT *
FROM bldb.dbo.blacklist
WHERE matchcode LIKE LEFT(dbo.fn_matchcode('12345','Sesame Street','1','Eddie','Bert'),13) + '%'
это все еще занимает несколько минут, чтобы закончить. Обратите внимание, что fn_matchcode
просто выполняет некоторые операции со строками и мгновенно возвращает.
Когда я жестко закодировал результат fn_matchcode
в запросе:
-- Query 5
SELECT *
FROM bldb.dbo.blacklist
WHERE matchcode LIKE '12345SSMSTRT1%'
это займет пару миллисекунд! Как бы вы это объяснили?