table scan意味着未走索引,需补索引或改写查询;navicat 17的“missing index”建议仅为启发式提示,须验证字段顺序、选择性及是否冗余,再结合隐式转换、函数使用和统计信息更新综合优化。
navicat 17 执行计划出现 table scan 意味着没走索引,必须补索引或改写查询
table scan 是执行计划里最危险的信号之一:数据库正逐行扫描整张表。哪怕只有 10 万行,i/o 和 cpu 开销也远超必要。navicat 17 自带的“missing index”建议(在执行计划右键菜单中)只是启发式提示,不能直接照搬——它不考虑字段顺序、选择性、重复索引或业务查询模式。
-
Table Scan出现在type列(MySQL)或LogicalOp列(SQL Server)中,对应成本高、rows值接近表总行数 - Navicat 17 的“Missing Index”建议仅基于当前 SQL 的 WHERE / JOIN / ORDER BY 字段生成,不校验这些字段是否已存在于其他复合索引中
- 如果表已有
INDEX (a, b),而查询只用WHERE b = ?,建议仍可能输出INDEX (b)—— 实际上这是冗余的
如何验证 Missing Index 是否真有用
别急着建索引。先确认这个建议是否解决实际瓶颈:
- 在 Navicat 中右键执行计划 → “Missing Index Details”,看它建议的字段组合是否覆盖了你的全部过滤条件、连接键和排序字段
- 检查该字段组合是否已在现有索引中作为最左前缀出现。例如查询
WHERE status = ? AND created_at > ? ORDER BY id,而你已有INDEX (status, created_at, id),那就不需要新索引 - 运行
SHOW INDEX FROM table_name,比对Seq_in_index和Cardinality:如果建议字段的基数(唯一值数量)极低(如status只有 3 个值),即使加了索引,优化器也可能弃用它,继续Table Scan - 对比
EXPLAIN FORMAT=JSON输出中的filtered值:若低于 10%,说明该条件筛选性差,索引收益有限
建索引时最容易踩的三个坑
Navicat 17 的索引创建界面很友好,但字段顺序、类型和时机选错,等于白干:
- 索引字段顺序必须严格匹配查询中 等值条件 → 范围条件 → ORDER BY / GROUP BY 字段 的顺序。比如
WHERE tenant_id = ? AND create_time > ? ORDER BY updated_at DESC,正确索引是INDEX (tenant_id, create_time, updated_at);把create_time放第一位就无效 - 不要对
TEXT、JSON或过长的VARCHAR字段建全文索引以外的 B-tree 索引——Navicat 可能允许建,但 MySQL 会截断前 767 字节(InnoDB 默认),导致索引失效 - 避免在高并发写入表上立刻建大索引:
ALTER TABLE ... ADD INDEX在 MySQL 5.7+ 仍会阻塞 DML(除非用ALGORITHM=INPLACE且满足条件)。建议在低峰期操作,或用 pt-online-schema-change 工具
当 Missing Index 建了还是 Table Scan,下一步查什么
索引存在 ≠ 被选用。常见干扰项藏在细节里:
- 隐式类型转换:查询用
WHERE user_id = '123'(字符串),而字段是INT,MySQL 会放弃索引。改成WHERE user_id = 123 - 函数包裹字段:
WHERE DATE(create_time) = '2024-01-01'必然跳过索引。应改写为WHERE create_time >= '2024-01-01' AND create_time - 统计信息过期:执行
ANALYZE TABLE table_name强制刷新,尤其在大批量 INSERT/DELETE 后 - 优化器误判:小表(如 Table Scan 反而是合理选择,不用强求索引
真正卡住的地方,往往不是“要不要建索引”,而是“建在哪几个字段上、按什么顺序、配合什么样的查询写法”。Navicat 17 的 Missing Index 是起点,不是终点。











