问题描述
在数据库中,对无索引的表进行查询或者有索引但是MySQL查询优化器不选择使用索引而进行的查询被称为全表扫描。如何判断当前某个
对语句执行EXPLAIN命令,如果Type列显示的结果为“ALL”,则说明MySQL 本次执行使用了全表扫描。
代码语言:javascript复制mysql> explain select * from servers;
---- ------------- --------- ------ --------------- ------ --------- ------ ------ -------
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
---- ------------- --------- ------ --------------- ------ --------- ------ ------ -------
| 1 | SIMPLE | servers | ALL | NULL | NULL | NULL | NULL | 1 | NULL |
---- ------------- --------- ------ --------------- ------ --------- ------ ------ -------
1 row in set (0.03 sec)
这通常发生在以下情况下:
- 表的行数太少,MySQL优化器认为全表扫描一遍比使用索引更高效,一般发生在少于 10 行且行长度较短的表。
- 在where或者on子句上涉及到的字段,没有可用的索引。
- 通过索引字段与常数值进行条件匹配,MySQL优化器基于索引计算出扫描的记录数太多,超过全表记录的30%,优化器认为全表扫描性能将比走索引更好。
- 在一个区分度不好的字段上建索引,比如性别,查询男性或者女性,即使在性别字段上建索引,优化器认为走索引性能并不如全表扫描好。
对于记录数比较小的表,全表扫描并不会对性能产生太大的影响,有时候反而会提高性能。但是随着数据量的增加,全表扫描会越来越慢,因此应当尽可能的避免全表扫描。
解决方案
MySQL如何避免全表扫描
- 在where条件或者join的连接字段上添加合适的索引,大多数全表扫描是由于忘了加索引导致
- ANALYZE TABLE tbl_name,更新索引分布统计信息,帮助优化器更准确地评估执行成本,产生更优的执行计划。
- FORCE INDEX,让MySQL优化器强制走某个索引。
- 设置参数--max-seeks-for-key=1000 或者 SET max_seeks_for_key=1000,这个值设置的越小,MySQL优化器越倾向于走索引,而不是全表扫描。
参考文章:https://dev.mysql.com/doc/refman/5.7/en/table-scan-avoidance.html