web-dev-qa-db-fra.com

Quelle requête SQL est meilleure, MATCH AGAINST ou LIKE?

Pour rechercher dans la base de données des lignes qui ont les deux mots-clés "foo" ET "bar" dans l'une des colonnes "foo_desc" et "bar_desc", je ferais quelque chose comme:

SELECT * 
FROM t1 
WHERE MATCH (t1.foo_desc, t2.bar_desc) AGAINST ('+foo* +bar*' IN BOOLEAN MODE)

ou

SELECT * 
FROM t1 
WHERE (CONCAT(t1.foo_desc, t2.bar_desc) LIKE '%foo%') AND (CONCAT(t1.foo_desc, t2.bar_desc) LIKE '%bar%')

Je m'attends à ce que l'inconvénient de la dernière requête soit la performance.

L'avantage est que la requête LIKE trouve 'xxfoo' là où MATCH AGAINST ne le fait pas.

Quelle est la solution préférée ou existe-t-il une meilleure solution?

66
Wil

Mise à jour

À partir du MySQL 5.6 et versions ultérieures, InnoDB tables prend en charge Match... Against.


Le premier est beaucoup mieux. Sur les tables MyISAM, il utilisera un index de texte intégral sur ces colonnes. L'autre fera une analyse complète de la table en faisant un concat sur chaque ligne, puis une comparaison.

LIKE n'est efficace que si vous le faites contre:

  • une colonne (pas le résultat d'une fonction, sauf si votre fournisseur de base de données particulier prend en charge les index fonctionnels - Oracle, par exemple - et que vous les utilisez);
  • le début de la colonne (c'est-à-dire LIKE 'blah%' par opposition à LIKE '%blah%'); et
  • une colonne indexée.

Si l'une de ces conditions n'est pas vraie, la seule façon pour le moteur SQL d'exécuter la requête consiste à effectuer une analyse complète de la table. Cela peut être utilisé sous environ 10 à 20 000 lignes. Au-delà, cela devient rapidement inutilisable cependant.

Note: Un problème avec MATCH sur MySQL est qu'il ne semble correspondre qu'à des mots entiers, donc une recherche de 'bla' ne correspondra pas à une colonne avec une valeur de 'blah', mais une recherche de 'bla *' le fera.

63
cletus