#sql #sql-server #performance #sql-server-2008
#sql #sql-сервер #Производительность #sql-server-2008
Вопрос:
Я пытаюсь выполнить поиск по свободному текстовому поиску и задаюсь вопросом, могу ли я улучшить этот запрос (используя MSSQL 2008):
@FreeText — это таблица, в которой каждая строка является поисковым словом
DECLARE @WordCount = (SELECT COUNT(*) from @FreeText)
SELECT p.ID
FROM Product p
OUTER APPLY
(
SELECT COUNT(ID) as MatchCount
FROM Product pm
INNER JOIN @FreeText ft
ON pm.txt like '%' ft.text '%'
WHERE pm.ID = p.ID
AND (SELECT TOP 1 [text] FROM @FreeText) IS NOT NULL
)MC
WHERE MatchCount = @WordCount
Итак, мне интересно, есть ли какой-либо способ избежать « FROM Product pm
» во внешнем приложении?
Я не всегда INNER JOIN @FreeText
могу, потому что иногда мы не используем поиск по свободному тексту.
Любые мысли или советы будут с благодарностью приняты, также дайте мне знать, если я смогу что-нибудь прояснить. Заранее спасибо.
PS Я знаю, что в MS SQL есть поиск FREETEXT (), но, к сожалению, я не могу его использовать в данный момент.
Комментарии:
1. Да, это работает довольно хорошо, если у вас есть другое предложение, я бы с удовольствием его выслушал… (Я знаю о поиске FREETEXT () в SQL, но не могу использовать это прямо сейчас).
Ответ №1:
Вот запрос без ВНЕШНЕГО ПРИМЕНЕНИЯ, который возвращает все результаты при отсутствии критериев поиска.
DECLARE @FreeText TABLE
(
[text] varchar(200)
)
INSERT INTO @FreeText SELECT 'a'
INSERT INTO @FreeText SELECT 'c'
-- what, null? No.
DELETE FROM @FreeText WHERE [text] is null
DECLARE @WordCount int
SET @WordCount = (SELECT Count(*) FROM @FreeText)
SELECT p.ID
FROM Product p
LEFT JOIN @FreeText ft
ON p.txt like '%' ft.text '%'
WHERE ft.text is not null OR @WordCount = 0
GROUP BY p.ID
HAVING COUNT(*) = @WordCount OR @WordCount = 0
Примечание: я бы предпочел не использовать запрос «freetext», когда нет никаких критериев свободного текста — вместо этого используйте другой запрос (более простой). Если вы решите пойти по этому пути — вернитесь к an INNER JOIN
и удалите OR @WordCount = 0
x2.
Комментарии:
1. Итак, если вы говорите не использовать запрос «freetext», когда нет критериев freetext, вы либо говорите о создании нескольких запросов для вызова, либо о создании динамического SQL, верно? К сожалению, учитывая природу других элементов во всем процессе, я не могу пойти по этим путям (я фактически преобразовал это из динамического SQL некоторое время назад). Я думаю, что в разгар всех моих настроек я потерял из виду левое соединение. Спасибо за предложение, мне придется профилировать два!
2. На самом деле, я только что вспомнил, почему я не могу выполнить левое соединение — я не могу позволить себе результат умножения строк этого соединения. Преимущество внешнего применения заключается в том, что я не умножаю строки, и в итоге запрос выполняется довольно быстро. Если у вас есть какие-либо другие мысли или предложения, я был бы признателен!
3. GroupBy решает эту проблему с умножением строк. Каждый идентификатор в результате уникален.
4. Из этих результатов и моего опыта кажется, что всякий раз, когда я выполняю умножение строк, мой запрос замедляется. На самом деле у меня есть несколько таких внешних приложений в одном запросе, потому что они избегают любого умножения строк. Даже при использовании group by в конце любое умножение строк может иметь отрицательный побочный эффект. Переход с моей версии на вашу привел к увеличению времени с 4 секунд до 14 секунд. Если у вас есть какие-либо другие мысли, я хотел бы услышать!