Skip to main content

23.避免全表扫描

当 MySQL 使用全表扫描来解析查询时,EXPLAIN 的输出会在类型列中显示 ALL。 这通常发生在以下条件下:

  • 该表非常小,因此执行表扫描比费心进行键查找要快。 这对于行数少于 10 行且行长度较短的表很常见。
  • 对于索引列,ON 或 WHERE 子句中没有可用的限制。
  • 正在将索引列与常量值进行比较,MySQL 已计算出(基于索引树)常量覆盖了表的过大部分,并且表扫描会更快。
  • 正在通过另一列使用基数较低的键(许多行与键值匹配)。 在这种情况下,MySQL 假设使用该键可能需要多次键查找,并且表扫描会更快。

对于小型表,表扫描通常是合适的,并且性能影响可以忽略不计。 对于大型表,请尝试以下技术以避免优化器错误地选择表扫描:

  • 使用 ANALYZE TABLE tbl_name 更新扫描表的键分布。

  • 对扫描的表使用 FORCE INDEX 来告诉 MySQL 与使用给定索引相比,表扫描的成本非常高:

    SELECT * FROM t1, t2 FORCE INDEX (index_for_column)
    WHERE t1.col_name=t2.col_name;
  • 使用 --max-seeks-for-key=1000 选项启动 mysqld 或使用 SET max_seeks_for_key=1000 告诉优化器假设没有键扫描会导致超过 1,000 个键查找。