代码之家  ›  专栏  ›  技术社区  ›  Mike Chamberlain JaredPar

跨多个表的SQL Server全文查询-为什么这么慢?

  •  7
  • Mike Chamberlain JaredPar  · 技术社区  · 16 年前

    我试图了解我正在构建的SQL Server 2008全文查询的性能。

    以下查询使用全文索引立即返回正确的结果:

    SELECT
        O.ID, O.Name
    FROM
        dbo.EventOccurrence O
    WHERE
        FREETEXT(O.Name, 'query')
    

    也就是说,所有事件的名称中都有“查询”一词。下面的查询使用来自不同表的全文索引,也会立即返回:

    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)为什么这么慢,(i i)是否支持这一点/我是否正确理解这一点。

    事先谢谢你的帮助。

    2 回复  |  直到 16 年前
        1
  •  11
  •   Joe Stefanelli    16 年前

    尝试使用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
    
        2
  •  1
  •   Martin Smith    16 年前

    这个比较的执行计划是怎样的?

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