2009-11-30 61 views
1

我有两个表:FreeText的统计查询是超级慢

**Product** 
ID 
Name 
SKU 

**Brand** 
ID 
Name 

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

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

我用自由文本 '包含' 这样的:

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秒。同样,如果我只检查品牌名称。如果我使用OR条件,则会发生该问题。

如果我切换查询中使用,如:

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

To search on multiple tables, use a joined table in your FROM clause to search on a result set that is the product of two or more tables.

所以我增加了一个INNER连接表来自:

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

这将导致错误: 不能使用CONTAINS或FREETEXT谓词列'ProductName',因为它没有全文索引。

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

+0

你对Product.BrandID的指数? – 2009-11-30 15:28:11

+0

是的,在Product.BrandID上有一个索引。 – 2009-12-02 09:05:57

回答

2

有点审判的错误后,我发现,似乎工作的解决方案。它涉及到创建索引视图:

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秒一次。

+0

谢谢!!在向视图添加索引之后,我继续将所有内容合并为一个包含子句。现在运行速度提高10倍。 – NotMe 2010-04-27 01:55:27

0

你有没有尝试过这样的:

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

我收到一个错误: 全文谓词引用来自两个不同表或索引视图'产品'和'品牌',这是不允许的。 – 2009-12-01 15:48:07

+0

噢,好吧;值得一试!另一个想法:我想知道你是否可以加入视图中的两个表格,然后查询视图? – RickNZ 2009-12-01 22:23:55

0

我遇到类似的问题,但我与工会固定它,像:

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