2010-03-05 64 views
3

我有一個帶有全文索引列的表MiddlePart。該表有大約600,000行。下面的查詢是非常快的(30個結果,< 1秒):爲什麼我的查詢很慢? (SQL Server 2008全文搜索奇怪)

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

這個查詢也非常快(5個結果,< 1秒):

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

那麼,爲什麼這兩個查詢超慢? (90秒+和我取消了查詢):

查詢:

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'))) 

編輯

用於查詢全文計劃:

|--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 
+0

你試圖改變第一個「UNION ALL」,而不只是「聯盟」:

在任何情況下,當面對這樣的陌生感臨時表始終是一個可敬的選擇嗎?你看過查詢計劃嗎?使用「OR」謂詞可能會搞砸查詢計劃。 – Pointy 2010-03-05 16:50:00

+0

您可以發佈查詢的查詢計劃嗎?只需運行SET SETPLAN_TEXT ON,然後運行查詢。 – Quassnoi 2010-03-05 16:52:04

+1

@OMGPonies:「我有一個帶有全文索引列'MiddlePart'的表格:) :) – Quassnoi 2010-03-05 16:53:48

回答

2

既然你不包括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