Almost everywhere I read the use of FORCE INDEX
is highly discouraged and I perfectly understand and know why - there are immensely huge chances that MySQL knows better what indexes to choose than the (average) developer.
However, recently I have found a case where FORCE INDEX
improved my execution times in the range of hundred of times:
JOIN
on 4 tables- first table has about 500 000 records
- 2 of the
INNER JOIN
ed table have more than 1 milion records - first table has a field called
published_date
, stored asvarchar
in YMD format (could not changed todatetime
) - needed a range on
published_date
of at most 5 000 records - some other
GROUP BY
andORDER BY
clauses on the first table on different fields thanpublished_date
were needed for this query
Although I've rewritten the query in many ways, I was not able to get execution times smaller than 130 seconds (with highest being over 700 ). After using FORCE INDEX
with published_date
, the execution time dropped below 5 seconds.
It took me a few days to remember about the infamous FORCE INDEX
option.
Questions:
- What are other use cases you found where
FORCE INDEX
saved you? - Do you have some best practices when you consider using
FORCE INDEX
?
Edit - Obsevations: I created this blog post with the question here also. All the answer you provide will appear there too - whith credits and all the stuff you want.
Edit 2
I applied the suggestions I received in your comments (ANALYZE TABLE
and OPTIMIZE TABLE
), below is the output of EXPLAIN
applied on query - unfortunately the index selection is not at all better:
1. without FORCE INDEX
on table with alias a
:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE am2 range PRIMARY,idx_meta_article idx_meta_article 4 NULL 275228 Using where; Using index; Using temporary; Using f...
1 SIMPLE a eq_ref PRIMARY,serial_issue_date_productid,pub_date,idx_d... PRIMARY 4 mydb_toto.am2.ArticleID 1 Using where
1 SIMPLE ai ref PRIMARY,idx_iso_article PRIMARY 4 mydb_toto.a.serial 11523 Using where; Using index
1 SIMPLE m range PRIMARY,meta_articles_type meta_articles_type 4 NULL 96 Using where
1 SIMPLE am eq_ref PRIMARY,idx_meta_article PRIMARY 8 mydb_toto.a.serial,mydb_toto.m.meta_id 1 Using where; Using index
2. with FORCE INDEX
on table with alias a
:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE a range pub_date pub_date 11 NULL 17679 Using where; Using temporary; Using filesort
1 SIMPLE am2 ref PRIMARY,idx_meta_article PRIMARY 4 mydb_toto.a.serial 21930 Using where; Using index
1 SIMPLE ai ref PRIMARY,idx_iso_article PRIMARY 4 mydb_toto.a.serial 11523 Using where; Using index
1 SIMPLE m range PRIMARY,meta_articles_type meta_articles_type 4 NULL 96 Using where
1 SIMPLE am eq_ref PRIMARY,idx_meta_article PRIMARY 8 mydb_toto.am2.ArticleID,mydb_toto.m.meta_id 1 Using where; Using index
3. after ANALYZE TABLE
, without FORCE INDEX
:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE am2 range PRIMARY,idx_meta_article idx_meta_article 4 NULL 275228 Using where; Using index; Using temporary; Using f...
1 SIMPLE a eq_ref PRIMARY,serial_issue_date_productid,pub_date,idx_d... PRIMARY 4 mydb_toto.am2.ArticleID 1 Using where
1 SIMPLE ai ref PRIMARY,idx_iso_article PRIMARY 4 mydb_toto.a.serial 11523 Using where; Using index
1 SIMPLE m range PRIMARY,meta_articles_type meta_articles_type 4 NULL 96 Using where
1 SIMPLE am eq_ref PRIMARY,idx_meta_article PRIMARY 8 mydb_toto.a.serial,mydb_toto.m.meta_id 1 Using where; Using index
4. after OPTIMIZE TABLE
, without FORCE INDEX
:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE am2 range PRIMARY,idx_meta_article idx_meta_article 4 NULL 275228 Using where; Using index; Using temporary; Using f...
1 SIMPLE a eq_ref PRIMARY,serial_issue_date_productid,pub_date,idx_d... PRIMARY 4 mydb_toto.am2.ArticleID 1 Using where
1 SIMPLE ai ref PRIMARY,idx_iso_article PRIMARY 4 mydb_toto.a.serial 11523 Using where; Using index
1 SIMPLE m range PRIMARY,meta_articles_type meta_articles_type 4 NULL 96 Using where
1 SIMPLE am eq_ref PRIMARY,idx_meta_article PRIMARY 8 mydb_toto.a.serial,mydb_toto.m.meta_id 1 Using where; Using index
5. after OPTIMIZE TABLE
and ANALYZE TABLE
, with FORCE INDEX
:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE a range pub_date pub_date 11 NULL 17679 Using where; Using temporary; Using filesort
1 SIMPLE am2 ref PRIMARY,idx_meta_article PRIMARY 4 mydb_toto.a.serial 21930 Using where; Using index
1 SIMPLE ai ref PRIMARY,idx_iso_article PRIMARY 4 mydb_toto.a.serial 11523 Using where; Using index
1 SIMPLE m range PRIMARY,meta_articles_type meta_articles_type 4 NULL 96 Using where
1 SIMPLE am eq_ref PRIMARY,idx_meta_article PRIMARY 8 mydb_toto.am2.ArticleID,mydb_toto.m.meta_id 1 Using where; Using index
ANALYZE TABLE
on the tables which you had toFORCE INDEX
onto? – Triplett