SQL Server и производительность для динамического поиска
Мне было интересно, каковы наилучшие методы для создания запроса в sql с динамическим значением, скажем, у меня есть значение (nvarchar (max))
Значение: "912345678"
select * from AllData
where Number like '%912345678%'
Значение: "Майкл"
select * from AllData
where Name like '%Michael%'
Значение: "номер улицы 10"
select * from AllData
where Address like '%Street number 10%'
Это приложение немного медленное, так как поиск числа, содержащего 9 цифр, был бы быстрее без %, как это
select * from AllData
where Number like '912345678'
Я использую EDMX для подключения к внешней базе данных на языке C#, вот так:
var Result = EDMXEntity.Entities.Where(x =>
(SqlFunctions.PatIndex("%" + Value.ToLower() +"%", x.Name.ToString().ToLower()) > 0)
|| (SqlFunctions.PatIndex("%" + Value.ToLower() +"%", x.Number.ToString().ToLower()) > 0)
|| (SqlFunctions.PatIndex("%" + Value.ToLower() +"%", x.Address.ToString().ToLower()) > 0)).Take(50).ToList();
Как я могу повысить производительность?
3 ответа:
Поиск по Подстановочным знакам, как эти на
varchar
/nvarchar
поля собираются перебирать каждый символ, более или менее, для записей, которые отвечают критерии.Великий (и быстрый!) вариант для этих видов поиска заключается в следующем:
- создайте полнотекстовый каталог для хранения полнотекстовых индексов.
- поместитеполнотекстовый индекс на столбцы в каждой таблице, которую вам нужно найти.
- используйте ключевое слово
CONTAINS
при поиске, а не подстановочные знаки.Вы упомянули о поиске для достоверных источников, здесь является хорошим чтением.
Если использование
LIKE
иPATINDEX
не дало вам требуемой производительности, то вам, вероятно, следует написать sp, который будет использовать FTS.
Для поиска с 'like' в EF вы можете использовать содержит():
Но при таком поиске вы никогда не добьетесь хорошей производительности. Вам нужно изменить способ поиска или хранения данных в БД. Например, если вы уверены, что пользователь искал имя, вы можете выполнить поиск только в столбце "имя".var Result = EDMXEntity.Entities.Where( x => x.Name.Contains(Value) || x => x.Number.ToString().Contains(Value) || x => x.Address.Contains(Value)).Take(50).ToList();