2010-12-01 7 views
0

Nous avons trois tables pour tenir nos produits et mots-clés:Algorithme de recherche par mot-clé SQL: Ce SQL effectue une recherche séquentielle, comment faire une recherche indexée?

Product {int ID, string name, ...} 
ProductKeyword {int productID, int keywordID} 
Keyword {int ID, string keyword} 

Ce code SQL retourne les produits les plus pertinents pour les produits les moins pertinents ayant des mots-clés tels que les utilisateurs recherchent des critères. searchWordTable est une table de mots de recherche. @keywordCount est le nombre de mots recherchés. Cela renvoie tous les produits ayant un ou plusieurs mots-clés, classés par quantité de mots-clés trouvés pour chaque produit.

select productid, productname, count(*) * 1/@keywordCount as percentRelevant 
from (select keyword, productid, productname 
     from product 
      join productkeyword on ... 
      join keyword on ... 
      join searchWordTable on searchwordtable.keyword like 
        '%' + keyword.keyword + '%') K -- like join aweful 
group by productid, productname 
order by percentRelevant desc -- Most relevant first 

Le problème est qu'il s'agit d'une recherche séquentielle comparant chaque mot clé que nous avons. Ce n'est pas mauvais, mais les recherches peuvent prendre une minute avec un million d'enregistrements.

Comment est-ce que je pourrais réécrire la requête pour ne pas utiliser like, j'espère utiliser une recherche indexée, et obtenir des résultats semblables? Ils utilisent like pour obtenir des correspondances partielles, par exemple, "os" dans "désossé".

Des liens vers de meilleurs algorithmes SQL seraient certainement appréciés.

+1

Dans votre exemple ("os" dans "désossé") vous pouvez omettre le premier "%" et - bang - un index peut être utilisé. – AndreKR

+0

C'est une très bonne idée. Si nous pouvions limiter nos mots-clés à des mots simples, cela fonctionnerait plutôt bien. Nous avons des mots-clés similaires à 'Kelloggs Corn Flakes'. –

Répondre

2

Comme vous tue, en particulier avec ce premier caractère générique qui supprime complètement les index que les colonnes peuvent avoir.

Vous devez examiner l'utilisation de l'indexation de texte intégral de SQL Server. contains sera probablement beaucoup plus rapide et est beaucoup plus puissant pour les matchs partiels de la nature que vous semblez faire.

1

Bien, vous pourriez implémenter un index de texte intégral sur cette colonne qui aiderait à la performance des instructions select, mais nuire aux performances des trois autres opérations CRUD car l'index devrait être mis à jour à chaque opération. Ensuite, je crois que vous utiliseriez un mot-clé CONTAINS ou un autre mot-clé similaire. Voici encore plus information.