SQL 2008: предотвращение полнотекстового поиска в запросе, когда в нем нет необходимости - PullRequest
1 голос
/ 04 ноября 2011

Работая над этой конкретной ситуацией, для меня стало новостью, что логические операторы не замыкаются накоротко в SQL.

Я обычно делаю что-то подобное в предложении where (обычно при работе с поисковыми запросами).):

WHERE
   (@Description IS NULL OR @Description = myTable.Description)

Что, даже если в этом примере оно не замкнуто, не имеет большого значения.Однако при работе с полнотекстовыми поисковыми функциями это имеет значение. Если вторая часть этого запроса была CONTAINS(myTable.Description, @Description), она не будет работать, поскольку переменная не может быть пустой или пустой для этих функций.

Я обнаружил, что WHEN операторы CASE выполняются по порядку, поэтому я могу изменить свой запрос следующим образом, чтобы полнотекстовый поиск вызывался только при необходимости, наряду с изменением переменной с нуля на '""'когда разрешено выполнение запроса: null:

WHERE
   (CASE WHEN @Description = '""' THEN 1 WHEN CONTAINS(myTable.Description, @Description) THEN 1 ELSE 0 END = 1)

Приведенный выше код должен препятствовать выполнению части полнотекстового запроса, если только нет фактического значения для поиска.

MyВопрос в том, что если я выполню этот запрос, где @Description равен '""', в плане выполнения все еще будет довольно много времени, затрачиваемого на поиск кластеризованного индекса и полное совпадение текста, даже если эта таблица и поиск не будут использоваться привсе: есть ли способ избежать этого?

Я пытаюсь получить это из жестко закодированного динамического запроса вЕсли процедура заканчивается медленнее, я не уверен, что смогу это оправдать.

Ответы [ 2 ]

0 голосов
/ 05 ноября 2011

В случае, если кто-то еще столкнется с подобным сценарием, это то, что я в итоге делал, что довольно близко к тому, к чему стремился M_M; Я разорвал полнотекстовые фрагменты и разместил их за ветвями:

DECLARE @TableBfullSearch TABLE (TableAId int)
IF(@TableBSearchInfo IS NOT NULL)
   INSERT INTO @TableBfullSearch
   SELECT
      TableAId
   FROM
      TableB
   WHERE
   ...(fulltext search)...

DECLARE @TableCfullSearch TABLE (TableAId int)
IF(@TableCSearchInfo IS NOT NULL)
   INSERT INTO @TableCfullSearch
   SELECT
      TableAId
   FROM
      TableC
   WHERE
   ...(fulltext search)...

--main query with this addition in the where clause
SELECT
  ...
FROM
   TableA
WHERE
   ...
   AND (@TableBSearchInfo IS NULL OR TableAId IN (SELECT TableAId FROM @TableBfullSearch))
   AND (@TableCSearchInfo IS NULL OR TableAId IN (SELECT TableAId FROM @TableCfullSearch))

Я думаю, что это примерно так же хорошо, как и без какого-либо динамического запроса

0 голосов
/ 04 ноября 2011

Это не идеально, но, возможно, что-то вроде этого будет работать:

IF @Description = ''
BEGIN 
     SELECT ...
END
ELSE
BEGIN
     SELECT ...
     WHERE CONTAINS(mytable.description, @Description)
END

Таким образом, вы избегаете mysql, а также запускаете сканирование FT, когда это не нужно.

Как несколько общих замечаний, я обычно нахожу CONTAINSTABLE немного быстрее.Кроме того, поскольку план запроса будет сильно отличаться, используете ли вы мое или ваше решение, следите за параметром sniffing .Обнаружение параметров - это когда оптимизатор строит план на основе переданного значения определенного параметра.

...