Настройка запроса сопоставления текста SQL

#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 секунд. Если у вас есть какие-либо другие мысли, я хотел бы услышать!