我有两张桌子:
**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条件可能导致慢查询?
答案 0 :(得分: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秒。
答案 1 :(得分:0)
你有没有试过像:
SELECT count(*)
FROM Product
INNER JOIN Brand ON Product.BrandID = Brand.ID
WHERE CONTAINS((Product.Name, Brand.Name), 'pants')
答案 2 :(得分: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'))