为什么要懂执行计划
SQL Server 慢查询优化,本质上就是”读懂执行计划 + 让优化器选对索引”。很多开发者只会加索引,但加完还是慢,因为没看执行计划到底走了没走。本文用实操带你把执行计划读明白。
一、怎么看执行计划
在 SSMS 里两种常用方式:
- 图形化:点”显示估计的执行计划”或”包括实际的执行计划”,执行后看拓扑图。
- 文本化:命令行更方便分析大数据量。
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
SELECT * FROM Orders WHERE CustomerId = 10086;
关注输出里的 逻辑读取 次数,这是衡量是否走索引最直接的指标——数字越小越好。
二、关键操作符识别
| 操作符 | 含义 | 是否该警惕 |
|---|---|---|
| Table Scan | 全表扫描 | 大表出现基本都要优化 |
| Index Seek | 索引查找 | 理想状态 |
| Key Lookup / RID Lookup | 书签查找(回表) | 频繁出现说明缺覆盖索引 |
| Sort | 排序 | 大结果集排序很贵 |
三、索引优化实战
假设查询频繁按 CustomerId 过滤并取 OrderDate, Total:
-- 基础非聚集索引
CREATE NONCLUSTERED INDEX IX_Orders_CustomerId
ON Orders(CustomerId);
-- 覆盖索引:把常用列 INCLUDE 进去,避免 Key Lookup 回表
CREATE NONCLUSTERED INDEX IX_Orders_CustomerId_Cover
ON Orders(CustomerId)
INCLUDE (OrderDate, Total);
加上 INCLUDE 后,执行计划里的 Key Lookup 会消失,逻辑读取从几千降到个位数。
四、最常见的几个坑
1. 列上套函数,索引失效
-- 不会走索引
SELECT * FROM Orders WHERE YEAR(OrderDate) = 2026;
-- 改写后走索引
SELECT * FROM Orders WHERE OrderDate >= '2026-01-01' AND OrderDate < '2027-01-01';
2. 隐式类型转换
字段是 varchar 但传入 nvarchar 参数,SQL Server 会对列做转换,导致索引失效。保持参数类型与列一致。
3. 前导通配符
-- 前导 % 必然全扫描
SELECT * FROM Products WHERE Name LIKE '%手机%';
-- 后导 % 才可能走索引
SELECT * FROM Products WHERE Name LIKE 'iPhone%';
五、统计信息别忘了
优化器靠统计信息估算行数。如果表长期大量增删但统计没更新,优化器可能选错计划。定期:
UPDATE STATISTICS Orders WITH FULLSCAN;
小结
执行计划不是玄学:先看有没有 Table Scan、有没有 Key Lookup、逻辑读取大不大,然后针对性建覆盖索引、改写法、更新统计。三板斧下来,大部分 SQL Server 慢查询都能解决。




