代码之家  ›  专栏  ›  技术社区  ›  Eric P

多个表上的FreeText计数查询速度非常慢

  •  1
  • Eric P  · 技术社区  · 15 年前

    我有两张桌子:

    **Product**
    ID
    Name
    SKU
    
    **Brand**
    ID
    Name
    

    我需要找到所有产品的名称和品牌匹配的特定关键字计数。

    我使用freetext的“包含”如下:

    SELECT count(*) 
    FROM   Product
           inner join Brand 
             on Product.BrandID = Brand.ID
    WHERE  (contains(Product.Name, 'pants') 
       or 
                contains(Brand.Name, 'pants'))
    

    此查询需要大约 在运行此查询之前,我重建了FreeText索引。

    如果我只检查Product.Name。他们的查询时间少于1秒。同样,只要我查一下品牌名称。如果我使用或使用条件,则会出现问题。

    如果我将查询切换为使用,如:

    SELECT count(*) 
    FROM   Product
           inner join Brand 
             on Product.BrandID = Brand.ID
    WHERE   Product.Name LIKE '%pants%'
       or 
                Brand.Name LIKE '%pants%'
    

    需要

    我在MSDN上看到: http://msdn.microsoft.com/en-us/library/ms187787.aspx

    要搜索多个表,请使用 搜索结果集,该结果集是 两个或多个表的乘积。

    因此,我在FROM中添加了一个内部联接表:

    SELECT count(*) 
    FROM   (select Product.Name ProductName, Product.SKU ProductSKU, Brand.Name as BrandName FROM Product
           inner join Brand 
             on product.BrandID = Brand.ID) as TempTable
    WHERE  
    
         contains(TempTable.ProductName, 'pants') 
         or 
                contains(TempTable.BrandName, 'pants') 
    

    这会导致错误: 无法对列“ProductName”使用CONTAINS或FREETEXT谓词,因为该列没有全文索引。

    所以问题是-为什么或条件会导致查询速度变慢?

    3 回复  |  直到 15 年前
        1
  •  2
  •   Eric P    14 年前

    经过一点尝试,我发现了一个似乎有效的解决方案。它涉及到创建索引视图:

    CREATE VIEW [dbo].[vw_ProductBrand]
    WITH SCHEMABINDING
    AS
    SELECT     dbo.Product.ID, dbo.Product.Name, dbo.Product.SKU, dbo.Brand.Name AS BrandName
    FROM         dbo.Product INNER JOIN
                          dbo.Brand ON dbo.Product.BrandID = dbo.Brand.ID
    
    GO
    
    CREATE UNIQUE CLUSTERED INDEX IX_VW_PRODUCTBRAND_ID 
        ON vw_ProductBrand (ID);
    GO
    

    DBCC DROPCLEANBUFFERS
    DBCC FREEPROCCACHE
    GO
    
    SELECT count(*) 
    FROM   Product
           inner join vw_ProductBrand
             on Product.BrandID =  vw_ProductBrand.ID
    WHERE  (contains(vw_ProductBrand.Name, 'pants') 
       or 
                contains( vw_ProductBrand.BrandName, 'pants'))
    

    现在需要 1秒 再一次。

        2
  •  0
  •   RickNZ    15 年前

    SELECT count(*) 
        FROM Product
        INNER JOIN Brand ON Product.BrandID = Brand.ID
        WHERE CONTAINS((Product.Name, Brand.Name), 'pants') 
    
        3
  •  0
  •   Gogutz Santosh Paswan    11 年前

    我遇到了类似的问题,但我用union解决了它,比如:

    SELECT *
    FROM   Product
           inner join Brand 
             on Product.BrandID = Brand.ID
    WHERE contains(Product.Name, 'pants') 
    
    UNION
    
    SELECT *
    FROM   Product
           inner join Brand 
             on Product.BrandID = Brand.ID
    WHERE contains(Brand.Name, 'pants'))