type为ALL即全表扫描,表明MySQL遍历整表匹配条件且未用有效索引;常见原因包括字段无索引、使用函数、隐式转换、LIKE左模糊等。

MySQL里看type字段是不是ALL
这是最直接的判断依据。执行EXPLAIN SELECT ...后,结果中type列显示ALL,就代表这条语句触发了全表扫描。
注意不是所有ALL都等于性能灾难:小表(比如sys.dm_db_partition_stats.row_count )走<code>ALL可能比索引Seek还快;但大表+小结果集时,ALL基本就是隐患信号。
-
type = ALL且rows接近表总行数 → 索引没被用上 -
type = index是全索引扫描,不是全表扫描,但也要警惕(尤其当Extra里没Using index) -
key列为NULL,说明没走任何索引,大概率对应ALL
PostgreSQL里认准Seq Scan节点
PostgreSQL的执行计划里,只要出现Seq Scan,就是全表扫描。它和Index Scan、Index Only Scan并列在“Access Methods”分类下,一眼就能区分。
别只看有没有Seq Scan,还要看它出现在哪一层:如果嵌套在Nested Loop里被反复执行(比如外层返回1000行,每行都触发一次Seq Scan),实际开销可能比单次扫描高几个数量级。
- 用
EXPLAIN (ANALYZE, BUFFERS)查真实I/O,shared hit低、read高,说明磁盘读多,常伴随Seq Scan -
Filter:后面带复杂表达式(如upper(name) = 'ABC'),即使有索引也容易退化成Seq Scan
Oracle中盯紧operation列的TABLE ACCESS FULL
Oracle执行计划里,operation列值为TABLE ACCESS FULL,就是明确的全表扫描标识。它通常和access predicates为空或只有filter predicates一起出现。
这里容易误判的是:如果access predicates有内容但filter predicates很长,说明索引只用于定位起始点,后续大量行靠服务端过滤——本质仍是低效扫描。
- 结合
rows(预估)和A-Rows(实际)对比:若A-Rows远超rows,统计信息可能过期,导致优化器误选FULL - 隐式转换常见于
WHERE id = '123'(id是NUMBER),Oracle会转成TO_NUMBER('123'),破坏索引可用性
真正危险的不是ALL本身,而是它藏在存储过程里
一个存储过程中可能有5条SELECT,但sys.dm_exec_procedure_stats只告诉你整体耗时高。想定位哪一句引发ALL,不能只看最终执行计划XML——它默认只展示顶层操作。
必须拆解验证:把存储过程里的每条SELECT、UPDATE、DELETE单独拎出来,加SET STATISTICS XML ON(SQL Server)或EXPLAIN ANALYZE(PostgreSQL/MySQL)跑一遍。
更隐蔽的问题是参数嗅探:WHERE status = @p1第一次传'pending'(高选择性),生成了索引计划;第二次传'completed'(占80%数据),复用旧计划反而走ALL。这种情况下OPTION (RECOMPILE)或sp_executesql动态拼接才是解法。

















