第一期:SQL Server 基础架构与核心组件
1. 实例(Instance)—— SQL Server 的“进程容器”
- 定义:一个独立的 SQL Server 服务进程(
sqlservr.exe),包含自己的一套系统数据库、用户数据库、配置和端口。 - 关键点:
- 一台机器可以装多个实例(默认实例 + 命名实例),彼此隔离,通过不同端口(默认 1433)区分。
- 每个实例有自己的内存、线程、调度器,但共享操作系统资源。
- 现象解释:为什么重启实例能清空某些缓存?因为实例重启会释放所有内存区域(如缓冲池、计划缓存)。
2. 系统数据库 —— SQL Server 自己的“控制面板”
| 数据库 | 作用 |
|---|---|
master | 记录实例级别信息(登录账号、链接服务器、配置、其他数据库位置) |
msdb | 存储作业、备份历史、维护计划、SQL Agent 相关信息 |
tempdb | 全局工作空间:存放临时表、排序、哈希连接、行版本、重建索引时的中间数据。每次实例重启会重新创建。 |
model | 任何新数据库的“模板” |
resource(只读隐藏) | 存储系统存储过程、视图等定义,升级时覆盖 |
- 现象解释:
tempdb负载过高导致全实例变慢?因为所有用户的排序、哈希、临时表都在抢同一个数据库。
3. 数据库(Database)与文件组(Filegroup)
- 数据库物理组成:
.mdf(主数据文件,1个).ndf(次数据文件,0~N个).ldf(事务日志文件,至少1个)
- 文件组:一组数据文件的逻辑容器。表和索引可以指定放在哪个文件组。
- 关键规则:
- 一个数据文件只属于一个文件组。
- 主文件组(
PRIMARY)永远包含主数据文件。 - 文件组内部采用比例填满策略(按空闲空间比例循环分配)。
- 现象解释:为什么把大表放到另一个文件组能改善 I/O?因为可以让多个物理硬盘并发读写,绕开主文件组的 I/O 瓶颈。
4. 执行引擎(Relational Engine)—— 负责“编译与执行”
主要处理 T-SQL 的整个生命周期:
-
Parser:语法检查,生成查询树。
-
Algebrizer:绑定到具体对象(视图、列、数据类型),生成逻辑树。
-
Optimizer:基于代价生成最优执行计划(关键:统计信息)。
-
Query Executor:调用存储引擎提供的数据访问方法,执行计划。
-
现象解释:
- 第一次执行慢,第二次快?——计划缓存在起作用(属于执行引擎的组件)。
- 参数嗅探问题?——优化器基于第一次传入的参数值生成计划,复用时可能不是最优。
5. 存储引擎(Storage Engine)—— 负责“数据怎么放、怎么取”
-
缓冲池(Buffer Pool):内存中最大区域,缓存数据页(8KB/页)。所有读/写最终都经过这里。
- 读:先查缓冲池 → 命中则直接返回;未命中则从磁盘读入缓冲池。
- 写:修改内存中的页(脏页),由 Checkpoint 或 LazyWriter 异步写回磁盘。
-
事务日志与 WAL(Write-Ahead Logging):
- 修改数据前,必须先写日志(日志刷盘后才允许修改内存页)。
- 保证 Crash Recovery 能回滚或重做。
-
数据访问方法:堆、B-Tree、聚集索引扫描、查找等。
-
锁与闩锁:
- 锁:事务隔离,协调用户并发(行、页、表锁)。
- 闩锁:保护内存结构(如缓冲池里的页),比锁更轻量、时间短。
-
现象解释:
- 为什么内存占满(不释放给 OS)?因为 SQL Server 把缓冲池当“缓存”,主动占用内存以减少磁盘 I/O。
- 为什么突然大量写磁盘?可能是 Checkpoint 或内存压力导致 LazyWriter 批量刷脏页。
- 为什么被阻塞?事务获得了锁不释放(例如更新未提交),另一个查询等待同样资源。
6. 完整工作流(一个 SELECT 语句从下发到返回)
客户端 → TDS 协议 → 实例端口(1433)
1. 协议层(SNI/Tabular Data Stream):解析请求,分发给执行引擎。
2. 执行引擎:解析→绑定→优化→生成执行计划(缓存)。
3. 存储引擎:
- 访问方法:根据计划调用“查找/扫描”接口。
- 缓冲池管理器:检查所需数据页是否在内存。
- 若不在 → 发起异步 I/O 从磁盘(.mdf/.ndf)读入缓冲池。
4. 存储引擎返回数据行给执行引擎。
5. 执行引擎处理聚合、排序等,最后通过协议层返回客户端。
更新语句(UPDATE) 则多走一步:
1. 在缓冲池修改数据页 → 标记为脏页。
2. 日志记录写入 `.ldf`(强刷盘)。
3. 事务提交时:日志被硬化,但脏页可能仍在内存(后续由 Checkpoint 写回)。
7. 常见“现象”与架构关联对照表
| 现象 | 直接原因 | 涉及架构组件 |
|---|---|---|
| 重启实例后第一次查询很慢 | 缓冲池为空,大量物理读 | 缓冲池、存储引擎 |
| 相同查询有时快有时慢 | 参数嗅探导致不同执行计划 | 优化器、计划缓存 |
| 大量临时表操作造成磁盘 I/O 瓶颈 | tempdb 争用或空间不足 | tempdb、存储引擎 |
| 查询被长时间阻塞 | 某事务持有行/表锁未释放 | 锁管理器 + 隔离级别 |
| 内存占用过高且不释放 | SQL Server 主动缓存数据页 | 缓冲池 |
| 突然长时间写盘任务 | Checkpoint / LazyWriter 刷脏页 | 检查点、缓冲池 |
第一期小结
SQL Server 的基础架构可以概括为:实例内有多个数据库(含系统库),每个数据库由文件组划分物理文件。执行引擎负责 T-SQL 的编译与优化,存储引擎管理内存(缓冲池)、磁盘 I/O、事务日志和并发控制。理解这些组件间的协作,就能解释或预判大多数性能问题。
下一期预告:深入 缓冲池与内存架构 —— 为什么缓存命中率决定性能?如何监控和调优内存压力?