70

To search the database for rows that have both keywords "foo" AND "bar" in any of the columns "foo_desc" and "bar_desc", I would do something like:

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

or

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

I expect the downside of the last query is performance.

The upside is that the LIKE query finds 'xxfoo' where MATCH AGAINST does not.

Which is the preferred one or is there a better solution?

Taryn
  • 242,637
  • 56
  • 362
  • 405
Wil
  • 892
  • 1
  • 8
  • 10

1 Answers1

69

Update

As of MySQL 5.6 and later, InnoDB tables supports Match... Against.


The first is much better. On MyISAM tables it will use a full text index against those columns. The other will do a full table scan doing a concat on every row and then a comparison.

LIKE is only efficient if you're doing it against:

  • a column (not a result of a function unless your particular database vendor supports functional indexes--Oracle, for example--and you're using them);
  • the start of the column (ie LIKE 'blah%' as opposed to LIKE '%blah%'); and
  • a column that's indexed.

If any one of those conditions are not true the only way for the SQL engine to execute the query is by doing a full table scan. This can be usable under about 10-20 thousand rows. Beyond that it quickly becomes unusable however.

Note: One problem with MATCH on MySQL is that it seems to only match against whole words so a search for 'bla' won't match a column with a value of 'blah', but a search for 'bla*' will.

Jai Chauhan
  • 4,035
  • 3
  • 36
  • 62
cletus
  • 616,129
  • 168
  • 910
  • 942
  • 22
    Comment on your note: MATCH will return columns with a value of blah if you search for bla* – Wil Apr 27 '09 at 10:16
  • 5
    @Strae `The minimum and maximum lengths of words to be indexed are defined by the innodb_ft_min_token_size and innodb_ft_max_token_size for InnoDB search indexes, and ft_min_word_len and ft_max_word_len for MyISAM ones.` https://dev.mysql.com/doc/refman/5.7/en/fulltext-fine-tuning.html – Lukas Liesis Feb 18 '17 at 20:26