Pergunta

Eu tenho duas tabelas:

**Product**
ID
Name
SKU

**Brand**
ID
Name

mesa O produto tem cerca de 120K registros mesa marca tem 30K registros

Eu preciso encontrar contagem de todos os produtos com nome e marca combinando uma palavra-chave específica.

Eu uso freetext 'contém' assim:

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

Esta consulta leva cerca de 17 segundos. Eu reconstruído o índice freetext antes de executar essa consulta.

Se eu só verificar Product.Name. Eles consulta é inferior a 1 segundo. Mesmo, se eu só verificar o Brand.Name. O problema ocorre se eu usar ou condição.

Se eu mudar consulta para usar como:

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

É preciso 1 seg.

Eu li no MSDN que: http://msdn.microsoft.com /en-us/library/ms187787.aspx

Para pesquisar em várias tabelas, use um juntou tabela em sua cláusula FROM para pesquisar em um conjunto de resultados que é o produto de duas ou mais tabelas.

Então eu adicionei uma tabela unida interior para 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') 

Isso resulta em erro: não pode usar um CONTÉM ou predicado FREETEXT na coluna 'ProductName' porque não é indexado por texto total.

Então a questão é - por que OR condição poderia estar causando tais como consulta lenta

Foi útil?

Solução

Depois de um pouco de tentativa um erro eu encontrei uma solução que parece funcionar. Ela envolve a criação de uma exibição indexada:

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

Se eu executar a consulta a seguir:

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

Agora leva 1 seg novamente.

Outras dicas

Você tentou algo como:

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

Eu tive um problema semelhante, mas eu fixa-lo com a união, algo como:

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'))
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top