Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLite: Should LIKE 'searchstr%' use an index?

I have a DB with several fields

word_id — INTEGER PRIMARY_KEY word — TEXT ... 

..and ~150k rows.

Since this is a dictionary, I'm searching for a word with mask 'search_string%' using LIKE. It used to work just fine, taking 15ms to find matching rows. The table has an index for a field 'word'. Recently I've modified the table (some fields of that table which are out of the scope) and something happened — it's taking 400ms to execute query, so I understand that as it fails to use index now. Straightforward query with = instead of like shows 10ms result. Does someone have an idea what's happening here?

like image 504
nikans Avatar asked Dec 21 '11 02:12

nikans


People also ask

Do like queries use index?

When you do LIKE '%text%' it can't use the index because there can be a variable number of characters before text. What you should be doing is not use a query like that at all. Instead you should use something like FTS (Full Text Search) that MySQL supports for MyISAM tables.

Does SQLite use index?

SQLite uses B-tree for organizing indexes. Note that B stands for balanced, B-tree is a balanced tree, not a binary tree. The B-tree keeps the amount of data at both sides of the tree balanced so that the number of levels that must be traversed to locate a row is always in the same approximate number.

Are primary keys automatically indexed SQLite?

Implicit IndexesIndexes are automatically created for primary key constraints and unique constraints. This will produce the following result, where sqlite_autoindex_COMPANY_1 is an implicit index which got created when the table itself was created.


1 Answers

An index cannot safely be used in this case. A naive implementation would transform this:

... WHERE word LIKE 'search_string%'

into

... WHERE word >= 'search_string' AND word < 'search_strinh'

by incrementing the last character of the search string. The greater-than and less-than operators can use an index, where LIKE cannot.

Unfortunately, that won't work in the general case. The LIKE operator is case-insensitive, which means that 'a' LIKE 'A' is true. The above transformation would break any search string with capitalized letters.

In some cases, however, you know that case sensitivity is irrelevant for a particular column, and the above transformation is safe. In this case, you have two options.

  1. Use the NOCASE collating sequence on the index that covers this particular field.
  2. Change the behavior of the LIKE operator program-wide by running PRAGMA case_sensitive_like = ON;

Either of these behaviors will enable SQLite to transparently do the above transformation for you; you just keep using LIKE as always, and SQLite will rewrite the underlying query to use the index.

You can read more about "The LIKE Optimization" on the SQLite Query Optimizer Overview page.

like image 142
BJ Homer Avatar answered Sep 20 '22 04:09

BJ Homer