Фон
У меня есть следующая функция, которая ранжирует результаты по тому, насколько близко они соответствуют искомому значению:
CREATE FUNCTION [dbo].[fnGetRelevance]
(
@fieldName nvarchar(50),
@searchTerm nvarchar(50)
)
RETURNS int
AS
BEGIN
if (@fieldName like @searchTerm + '%') -- starts with
begin
return 0
end
else if ((@fieldName like '%' + @searchTerm + '%') and (@fieldName not like @searchTerm + '%')) -- contains, but doesn't start with
begin
return 1
end
return 1
END
Так в контекстеследующего запроса (запрос NHibernate), который ищет классы общего ресурса на основе строки поиска Allianz RCM BRIC Stars A
, находит 39 результатов и ранжирует их так, чтобы тот, который точно совпадает с этой строкой, был сверху, а остальные отсортированы в алфавитном порядке нижеit.
select top 50 *
from ShareManager.ShareClass sc
-- and a few other tables with an inner join and a left join
where (sc.ShareClass_Id in
(
/* filter by some business criteria which is a single
select statement that does 2 more inner joins */
)
and 1 = 1
and (sc.ShareClass_Name like '%Allianz%' /* @p11 */)
and (sc.ShareClass_Name like '%RCM%' /* @p12 */)
and (sc.ShareClass_Name like '%BRIC%' /* @p13 */)
and (sc.ShareClass_Name like '%Stars%' /* @p14 */)
and (sc.ShareClass_Name like '%A%' /* @p15 */)
order by dbo.fngetrelevance(sc.ShareClass_Name, 'Allianz RCM BRIC Stars A'), sc.ShareClass_Name asc
Вопрос
Проблема, с которой я столкнулся, заключается в том, что dbo.fngetrelevance
вызывает тайм-аут моих запросов NHibernate.Я пытался продлить время ожидания, но это не работает, и я не думаю, что это действительно проблема в любом случае.Когда я удаляю функцию, она работает как положено.
Есть ли способ на SQL Server 2008 сделать это быстрее или реализовать ранжирование с помощью NHibernate таким образом, чтобы оно не истекло?
Дополнительная информация
Я ожидаю, что кто-то может предложить мне уменьшить количество объединений.Мы уже прошли большую оптимизацию, чтобы максимально ускорить эти запросы.Для нас было бы огромным усилием выяснить, как оптимизировать дальше, в масштабе изменения общей схемы.К сожалению, мы не собираемся добиваться этого на данном этапе игры (и только для 1 фонда, насколько я могу видеть на данный момент)
Для протокола, этокак я использую функцию с NHibernate:
string querystring =
"select sc, sctr" +
" from ShareClass as sc" +
// joins to 2 other tables
" and (" + expressionTokenizer.ToResult("sc.Name") + ") "
+ this.AddShareClassOrder(order, "sc", "sctr", searchExpression);
var result = _session.CreateQuery(querystring)
.AddNameSearchCriteria(expressionTokenizer)
.AddDataUniverseParameters(dataUniverseHelper)
.SetFirstResult((pageSize * (pageNum - 1)))
.SetMaxResults(pageSize)
.List();
с AddShareClassOrder
, эффективно возвращая
fieldName = string.Format("dbo.fngetrelevance({1}.{2}, '{0}'), {1}.{2}", textToSearchFor, shareClassPrefix, "Name");
return String.Format(" order by {0} {1}", fieldName, direction);
или, как это представлено в SQL:
dbo.fngetrelevance(sc.ShareClass_Name, 'Allianz RCM BRIC Stars A'), sc.ShareClass_Name asc