2009-11-30 60 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'))