Почему мой запрос такой медленный?(Странность полнотекстового поиска в SQL Server 2008) - PullRequest
3 голосов
/ 05 марта 2010

У меня есть таблица с полнотекстовым индексированным столбцом MiddlePart. Таблица имеет около 600 000 строк. Следующий запрос очень быстрый (30 результатов, <1 секунда): </p>

select * from DomainName
where contains (MiddlePart, '"antiques*"')
    OR freetext(MiddlePart, 'antiques')

Этот запрос также очень быстрый (5 результатов, <1 секунда): </p>

select * from DomainName
where (contains (MiddlePart, '"dog*"') OR freetext(MiddlePart, 'dog'))
    AND (contains (MiddlePart, '"training*"') OR freetext(MiddlePart, 'training'))

Так почему ОБА эти запросы ЧРЕЗВЫЧАЙНО медлительны? (90 секунд + и я отменил запрос):

Запрос A:

select * from DomainName
where contains (MiddlePart, '"antiques*"')
    OR freetext(MiddlePart, 'antiques')
union
select * from DomainName
where (contains (MiddlePart, '"dog*"') OR freetext(MiddlePart, 'dog'))
    AND (contains (MiddlePart, '"training*"') OR freetext(MiddlePart, 'training'))

Запрос B:

select * from DomainName
where (contains (MiddlePart, '"antiques*"')
    OR freetext(MiddlePart, 'antiques'))
OR
    ((contains (MiddlePart, '"dog*"') OR freetext(MiddlePart, 'dog'))
    AND (contains (MiddlePart, '"training*"') OR freetext(MiddlePart, 'training')))

EDIT

Полный текст плана для QUERY A:

|--Merge Join(Union)
   |--Nested Loops(Inner Join, OUTER REFERENCES:(FulltextMatch.[docid], [Expr1055]) WITH ORDERED PREFETCH)
   |    |--Stream Aggregate(GROUP BY:(FulltextMatch.[docid]))
   |    |    |--Merge Join(Concatenation)
   |    |         |--Table-valued function
   |    |         |--Table-valued function
   |    |--Clustered Index Seek(OBJECT:([domaining].[dbo].[DomainName].[PK__DomainNa__3214EC2708EA5793]), SEEK:([domaining].[dbo].[DomainName].[ID]=FulltextMatch.[docid]) ORDERED FORWARD)
   |--Merge Join(Left Semi Join, MERGE:([domaining].[dbo].[DomainName].[ID])=(FulltextMatch.[docid]), RESIDUAL:([domaining].[dbo].[DomainName].[ID]=FulltextMatch.[docid]))
        |--Nested Loops(Inner Join, OUTER REFERENCES:(FulltextMatch.[docid], [Expr1056]) WITH ORDERED PREFETCH)
        |    |--Stream Aggregate(GROUP BY:(FulltextMatch.[docid]))
        |    |    |--Merge Join(Concatenation)
        |    |         |--Table-valued function
        |    |         |--Table-valued function
        |    |--Clustered Index Seek(OBJECT:([domaining].[dbo].[DomainName].[PK__DomainNa__3214EC2708EA5793]), SEEK:([domaining].[dbo].[DomainName].[ID]=FulltextMatch.[docid]) ORDERED FORWARD)
        |--Merge Join(Concatenation)
             |--Table-valued function
             |--Table-valued function

Полный текст плана запроса B:

|--Nested Loops(Left Semi Join, OUTER REFERENCES:([domaining].[dbo].[DomainName].[ID]))
   |--Clustered Index Scan(OBJECT:([domaining].[dbo].[DomainName].[PK__DomainNa__3214EC2708EA5793]))
   |--Concatenation
        |--Table-valued function
        |--Nested Loops(Left Semi Join)
        |    |--Concatenation
        |    |    |--Table-valued function
        |    |    |--Table-valued function
        |    |--Row Count Spool
        |         |--Concatenation
        |              |--Table-valued function
        |              |--Table-valued function
        |--Table-valued function

1 Ответ

2 голосов
/ 07 марта 2010

Поскольку вы не включили SHOWPLAN для комбинированного запроса, я бы предположил, что он не вывел один, что указывало бы на ошибку в оптимизаторе. Известно, что это происходит в других местах.

В любом случае, временные таблицы всегда достойный выбор, когда сталкиваются с такой странностью:

select * into #a from DomainName
where contains (MiddlePart, '"antiques*"')
    OR freetext(MiddlePart, 'antiques')

select * into #b from DomainName
where (contains (MiddlePart, '"dog*"') OR freetext(MiddlePart, 'dog'))
    AND (contains (MiddlePart, '"training*"') OR freetext(MiddlePart, 'training'))

select * from #a union #b
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...