How MySQL full-text search works: FULLTEXT indexes, MATCH…AGAINST syntax, natural language vs boolean mode vs query expansion, and when to use full-text vs LIKE.
Use this file to discover all available pages before exploring further.
VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
MySQL’s LIKE '%keyword%' works for small tables but can’t use indexes — every row gets scanned. Full-text search gives you an indexed, ranked alternative for searching text columns.
MySQL returns rows in descending relevance order when MATCH...AGAINST appears in the WHERE clause. The AGAINST expression returns a relevance score — 0 means no match.
The default. MySQL uses a weighting scheme that effectively ignores extremely common words — terms appearing in nearly all rows contribute little to relevance scores. Common English stopwords (the, is, at) are filtered outright. Results are returned in descending relevance order when no explicit ORDER BY is present.
-- Returns rows matching 'index' or 'query', ranked by relevanceSELECT title FROM articlesWHERE MATCH(title, body) AGAINST('index query');
Boolean mode supports operators for precise control:
-- Must contain 'index', must not contain 'slow', 'performance' is optionalSELECT title FROM articlesWHERE MATCH(title, body) AGAINST('+index -slow performance' IN BOOLEAN MODE);
Common boolean operators:
Operator
Meaning
Example
+
Word must be present
+index
-
Word must not be present
-slow
*
Prefix wildcard
perform*
""
Phrase match
"query optimizer"
><
Increase/decrease relevance
>fast <slow
()
Grouping
+(index query) -slow
InnoDB tables require a FULLTEXT index on all columns in the MATCH() expression — without it, boolean mode queries on InnoDB return an error. (MyISAM permits boolean mode without a FULLTEXT index but will scan every row.)
Two-pass search. MySQL runs the initial query, takes the top matches, extracts additional terms from them, then re-runs the search with those terms added.
SELECT title FROM articlesWHERE MATCH(title, body) AGAINST('database' WITH QUERY EXPANSION);
Useful when users search with single or vague terms. Can return surprising results if the top matches from the first pass are off-topic.
Use LIKE for simple pattern matching on small tables, prefix searches (LIKE 'prefix%' with an index), or when you need arbitrary pattern matching. Use full-text when you’re searching for words or phrases in text columns and need relevance ranking or better performance at scale.
InnoDB’s default minimum token size is 3 characters (innodb_ft_min_token_size). Words shorter than 3 characters are not indexed. For two-character words, lower the minimum:
-- In my.cnf / my.ini[mysqld]innodb_ft_min_token_size = 2
innodb_ft_min_token_size is not a dynamic variable — it requires a server restart to take effect. After restarting, rebuild all FULLTEXT indexes:
Why does my MATCH…AGAINST return no rows even though the word is in the table?
Three common reasons: (1) The word is shorter than innodb_ft_min_token_size (default 3). (2) The word is in the stopword list. (3) The word appears in more than 50% of rows — natural language mode treats such words as too common to be useful. Use boolean mode to bypass the 50% threshold.
Does MySQL full-text search support multiple languages?
MySQL has built-in stopword lists for several languages. For production multilingual search, you’ll typically need to configure innodb_ft_enable_stopword = OFF and supply your own stopword table via innodb_ft_server_stopword_table, or use an external search engine (Elasticsearch, MeiliSearch).