Search code examples
mysqlsqlfull-text-searchquery-optimizationquery-performance

Optinimizing query with fts + composite index


I have the following query:

SELECT * 
FROM table 
WHERE 
    structural_type=1 
    AND parent_id='167F2-F' 
    AND points_to_id=''
    # AND match(search) against ('donotmatch124213123123')

The search takes about 10ms to run, running on the composite index (structural_type, parent_id, points_to_id). However, when I add in the fts index, the query balloons to taking ~1s, regardless of what is contained in the match criteria. Basically it seems like it 'skips the index' whenever I have a fts search applied.

What would be the best way to optimize this query?

Update: a few explains:

EXPLAIN SELECT... # without fts

id  select_type table   partitions  type    possible_keys   key key_len ref rows    filtered    Extra
1   SIMPLE  table   NULL    ref structural_type structural_type 209 const,const,const   2   100.00  NULL

With fts (also adding 'force index'):

explain SELECT ... force INDEX (structural_type) AND match...

id  select_type table   partitions  type    possible_keys   key key_len ref rows    filtered    Extra
1   SIMPLE  table   NULL    fulltext    structural_type,search  search  0   const   1   5.00    Using where; Ft_hints: sorted

The only thing I can think of which would be incredibly hack-ish, would be to add an additional term to the fts so it does the filter 'within' that. For example:

fts_term = fts_term += " StructuralType1ParentID167F2FPointsToID"

Solution

  • The MySQL optimizer can only use one index for your WHERE clause, so it has to choose between the composite one and the FULLTEXT one.

    Since it can't run both queries to bench which one is faster, it will estimate how fast will different execution plans be.

    To do so, MySQL uses some internal stats it keeps about each table. But those stats can be very different from the reality if they aren't updated and the data changes in the table.

    Running a OPTIMIZE TABLE table query allows MySQL to refresh its table stats, so it will be able to perform better estimates and choose the better index.