几乎所有我读到的地方都不建议使用
然而,最近我发现了一种情况,在这种情况下,
让我花了几天时间才想起臭名昭著的 1. 在别名为
2. 使用别名为
3. 在执行
4. 在没有
5. 在使用
FORCE INDEX
,我非常理解并知道为什么——MySQL比(普通)开发人员更有可能知道选择哪些索引。然而,最近我发现了一种情况,在这种情况下,
FORCE INDEX
将我的执行时间提高了数百倍:
- 在4个表上进行
JOIN
- 第一个表约有500,000条记录
- 2个
INNER JOIN
的表中有超过1百万条记录 - 第一个表有一个名为
published_date
的字段,以YMD格式存储为varchar
(无法更改为datetime
) - 需要对最多5,000条记录的
published_date
范围进行筛选 - 此查询需要在第一个表上使用其他与
published_date
不同的字段进行GROUP BY
和ORDER BY
子句
published_date
的FORCE INDEX
后,执行时间降至5秒以下。让我花了几天时间才想起臭名昭著的
FORCE INDEX
选项。
问题:
- 你发现在哪些其他用例中使用
FORCE INDEX
可以节省时间? - 在考虑使用
FORCE INDEX
时,您是否有一些最佳实践?
编辑-观察: 我使用此处的问题创建了这篇博客文章。您提供的所有答案也将出现在那里-带有信用和所有您想要的内容。
编辑2:
我应用了您在评论中收到的建议(ANALYZE TABLE
和OPTIMIZE TABLE
),下面是应用于查询的EXPLAIN
输出-不幸的是,索引选择并没有改善:
1. 在别名为a
的表上没有使用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
2. 使用别名为a
的表和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
3. 在执行ANALYZE TABLE
之后,不使用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. 在没有 FORCE INDEX
的情况下,执行 OPTIMIZE TABLE
:
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. 在使用OPTIMIZE TABLE
和ANALYZE TABLE
之后,再加上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
FORCE INDEX
的表上运行了ANALYZE TABLE
命令? - Romain