SQL, созданный Entity Framework для сопоставления строк - PullRequest
7 голосов
/ 29 января 2009

Учитывая этот запрос linq к контексту данных EF:

var customers = data.Customers.Where(c => c.EmailDomain.StartsWith(term))

Вы ожидаете, что он будет производить SQL, как это, верно?

SELECT {cols} FROM Customers WHERE EmailDomain LIKE @term+’%’

Ну, вообще-то, он делает что-то вроде этого:

SELECT {cols} FROM Customer WHERE ((CAST(CHARINDEX(@term, EmailDomain) AS int)) = 1)

Знаешь почему?

Кроме того, замена селектора Where на:

c => c.EmailDomain.Substring(0, term.Length) == term

он работает в 10 раз быстрее, но все равно выдает довольно неприятный SQL.

ПРИМЕЧАНИЕ: Linq to SQL правильно переводит StartsWith в Like {term}%, а nHibernate имеет выделенное выражение LikeExpression.

Ответы [ 5 ]

3 голосов
/ 27 сентября 2010

Я не знаю, что такое сервер MS SQL, но на компактном сервере SQL LIKE 'foo%' в тысячи раз быстрее, чем CHARINDEX, если у вас есть индекс в столбце поиска. А теперь я сижу и вытаскиваю свои волосы, как заставить их использовать LIKE.

http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/1b835b94-7259-4284-a2a6-3d5ebda76e4b

2 голосов
/ 29 января 2009

Причина в том, что CharIndex намного быстрее и чище для SQL, чем LIKE. Причина в том, что вы можете иметь некоторые сумасшедшие предложения "LIKE". Пример:

SELECT * FROM Customer WHERE EmailDomain LIKE 'abc%de%sss%'

Но функция "CHARINDEX" (которая в основном "IndexOf") обрабатывает ТОЛЬКО поиск первого экземпляра набора символов ... подстановочные знаки не допускаются.

Итак, вот ваш ответ:)

РЕДАКТИРОВАТЬ: Я просто хотел добавить, что я призываю людей использовать CHARINDEX в своих SQL-запросах для вещей, для которых им не нужно "LIKE". Важно отметить, что в SQL Server 2000 ... поле «Текст» может использовать метод LIKE , но не CHARINDEX.

0 голосов
/ 01 апреля 2009

Я согласен, что это не так быстро, я извлекал десятки тысяч строк из нашей базы данных с буквой «i». Однако я обнаружил, что вам нужно использовать>, а не = ... так что используйте

{cols} FROM Customer WHERE ((CAST(CHARINDEX(@term, EmailDomain) AS int)) > 0)

вместо

{cols} FROM Customer WHERE ((CAST(CHARINDEX(@term, EmailDomain) AS int)) = 1)

Вот мои два теста ....

select * from members where surname like '%i%'    --12 seconds

select * from sc4_persons where ((CAST(CHARINDEX('i', surname) AS int)) > 0)  --12 seconds

select * from sc4_persons where ((CAST(CHARINDEX('i', surname) AS int)) = 1)  --too few results
0 голосов
/ 29 января 2009

charindex возвращает местоположение первого слагаемого в пределах второго слагаемого.

sql начинается с 1 в качестве первого местоположения (0 = не найдено)

http://msdn.microsoft.com/en-us/library/ms186323.aspx

я не знаю, почему он использует этот синтаксис, но вот как он работает

0 голосов
/ 29 января 2009

Производительность между LIKE и CHARINDEX примерно одинакова, поэтому причина не в этом. См. здесь или здесь для некоторого обсуждения. Также CAST очень странный, потому что CHARINDEX возвращает int.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...