Question

J'ai deux tables:

**Product**
ID
Name
SKU

**Brand**
ID
Name

La table des produits contient environ 120 000 enregistrements. La table des marques contient 30 000 enregistrements

Je dois trouver le nombre de tous les produits dont le nom et la marque correspondent à un mot clé spécifique.

J'utilise le texte libre 'contient' comme ceci:

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

Cette requête prend environ 17 secondes. J'ai reconstruit l'index FreeText avant d'exécuter cette requête.

Si je ne vérifie que Product.Name. Leur requête est inférieure à 1 seconde. Pareil, si je vérifie seulement le nom Brand.Name. Le problème se produit si j'utilise la condition OR.

Si je change de requête pour utiliser LIKE:

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

Cela prend 1 seconde.

J'ai lu sur MSDN que: http://msdn.microsoft.com /en-us/library/ms187787.aspx

  

Pour rechercher sur plusieurs tables, utilisez un   table jointe dans votre clause FROM à   rechercher sur un résultat qui est le   produit de deux ou plusieurs tables.

J'ai donc ajouté une table 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') 

Cela entraîne une erreur: Impossible d'utiliser un prédicat CONTAINS ou FREETEXT sur la colonne 'ProductName' car il n'est pas indexé en texte intégral.

La question est donc de savoir pourquoi une condition OR pourrait être provoquée, telle qu'une requête lente?

Était-ce utile?

La solution

Après une petite tentative d’essai, j’ai trouvé une solution qui semble fonctionner. Cela implique la création d’une vue indexée:

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

Si j'exécute la requête suivante:

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

Il faut maintenant 1 seconde .

Autres conseils

Avez-vous essayé quelque chose comme:

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

J'ai rencontré un problème similaire, mais je l'ai résolu avec l'union, quelque chose comme:

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'))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top