Я пытаюсь понять производительность полнотекстового запроса SQL Server 2008 года, который я создаю.
Следующий запрос, с помощью полнотекстового индекса, сразу возвращает корректные результаты:
SELECT
O.ID, O.Name
FROM
dbo.EventOccurrence O
WHERE
FREETEXT(O.Name, 'query')
т.е., все EventOccurrences со словом 'запрашивают' на их имя. И следующий запрос, с помощью полнотекстового индекса от другой таблицы, также немедленно возвращается:
SELECT
V.ID, V.Name
FROM
dbo.Venue V
WHERE
FREETEXT(V.Name, 'query')
т.е. все Места проведения со словом 'запрашивают' на их имя. Но если я пытаюсь присоединиться к таблицам и сделать оба полнотекстовых запроса сразу, это 12 секунд для возврата:
SELECT
O.ID, O.Name
FROM
dbo.EventOccurrence O
INNER JOIN dbo.Event E ON O.EventID = E.ID
INNER JOIN dbo.Venue V ON E.VenueID = V.ID
WHERE
FREETEXT(E.Name, 'search')
OR FREETEXT(V.Name, 'search')
Вот план выполнения: http://uploadpad.com/files/query.PNG
ОБНОВЛЕНИЕ: план в в текстовой форме:
|--Nested Loops(Left Semi Join, OUTER REFERENCES:([E].[ID], [V].[ID]))
|--Hash Match(Inner Join, HASH:([E].[ID])=([O].[EventID]))
| |--Hash Match(Inner Join, HASH:([V].[ID])=([E].[VenueID]))
| | |--Clustered Index Scan(OBJECT:([iScene].[dbo].[Venue].[PK_Venue] AS [V]))
| | |--Clustered Index Scan(OBJECT:([iScene].[dbo].[Event].[PK_Event] AS [E]))
| |--Clustered Index Scan(OBJECT:([iScene].[dbo].[EventOccurrence].[PK_EventOccurrence] AS [O]))
|--Concatenation
|--Table-valued function
|--Table-valued function
От моего чтения я не думал, что было даже возможно сделать бесплатный текстовый запрос через несколько таблиц таким образом, таким образом, я не уверен, что понимаю это правильно.
Обратите внимание, что, если я удаляю оператор Where из этого последнего запроса затем, он возвращает все результаты в течение секунды, таким образом, это - определенно полнотекстовое, которое вызывает проблему здесь.
Может кто-то объяснять (i) почему это настолько медленно и (ii) если это даже поддерживается / если я даже понимаю это правильно.
Заранее спасибо за Вашу справку.
Попробуйте переписать запрос, используя FREETEXTTABLE, и посмотрите, поможет ли это.
SELECT
O.ID, O.Name
FROM
dbo.EventOccurrence O
INNER JOIN dbo.Event E ON O.EventID = E.ID
INNER JOIN dbo.Venue V ON E.VenueID = V.ID
LEFT JOIN FREETEXTTABLE(dbo.Event, Name, 'search') EFT
ON E.ID = EFT.[KEY]
LEFT JOIN FREETEXTTABLE(dbo.Venue, Name, 'search') VFT
ON V.ID = VFT.[KEY]
WHERE EFT.[KEY] IS NOT NULL OR VFT.[KEY] IS NOT NULL
Как выглядит план выполнения для этого?
SELECT
O.ID, O.Name
FROM
dbo.EventOccurrence O
WHERE O.EventID IN (
SELECT
E.ID
FROM
dbo.Event E
WHERE
FREETEXT(E.Name, 'search')
UNION
SELECT
E.ID
FROM
dbo.Event E
INNER JOIN dbo.Venue V ON E.VenueID = V.ID
WHERE
FREETEXT(V.Name, 'search')
)