我有两张桌子:

**Product**
ID
Name
SKU

**Brand**
ID
Name

产品表有大约120K的记录 品牌表有30K记录

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

我使用freetext'contains'这样:

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

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

如果我只检查Product.Name。他们的查询时间不到1秒。同样,如果我只检查Brand.Name。如果我使用OR条件,则会出现此问题。

如果我切换查询以使用LIKE:

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

需要 1秒

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

  

要搜索多个表,请使用   将FROM子句中的表连接到   搜索结果集   两个或多个表格的产品。

所以我将一个INNER JOINED表添加到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谓词,因为它不是全文索引。

所以问题是 - 为什么OR条件可能导致慢查询?

有帮助吗?

解决方案

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

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秒

其他提示

你有没有试过像:

SELECT count(*) 
    FROM Product
    INNER JOIN Brand ON Product.BrandID = Brand.ID
    WHERE CONTAINS((Product.Name, Brand.Name), 'pants') 

我遇到了类似的问题,但我用工会修复了它,比如:

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'))
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top