外观
SQLServer 物理架构
SQL Server 物理架构描述了数据在磁盘上的存储方式和组织形式,包括数据库文件、文件组、页面结构和I/O管理等。了解 SQL Server 物理架构对于 DBA 来说至关重要,它有助于优化存储设计、提高 I/O 性能和确保数据安全。本文将详细介绍 SQL Server 的物理架构,包括核心组件、存储结构和最佳实践。
数据库文件
SQL Server 数据库由三种类型的文件组成:
1. 主要数据文件 (Primary Data File)
- 扩展名:.mdf
- 作用:包含数据库的系统表和元数据
- 要求:每个数据库必须有且只有一个主要数据文件
- 默认位置:通常位于 SQL Server 安装目录的 DATA 文件夹
- 大小限制:最大可达 524 PB
2. 次要数据文件 (Secondary Data Files)
- 扩展名:.ndf
- 作用:存储用户数据,可以分散到多个磁盘以提高 I/O 性能
- 要求:可选,每个数据库可以有零个或多个次要数据文件
- 位置:可以位于不同的磁盘驱动器上
- 大小限制:最大可达 524 PB
3. 事务日志文件 (Transaction Log File)
- 扩展名:.ldf
- 作用:记录所有数据修改操作,用于恢复和回滚事务
- 要求:每个数据库至少有一个事务日志文件
- 位置:建议与数据文件放在不同的磁盘上,以提高性能和安全性
- 大小限制:最大可达 524 PB
文件组
文件组是数据库文件的逻辑集合,用于组织和管理数据文件:
1. 主要文件组 (Primary Filegroup)
- 包含主要数据文件和所有未指定文件组的对象
- 包含系统表和元数据
- 不能被删除
2. 用户定义文件组
- 由用户创建,用于组织用户数据
- 可以包含一个或多个数据文件
- 可以用于优化 I/O 性能,将不同的表或索引分配到不同的文件组
3. 默认文件组
- 新创建的对象默认所属的文件组
- 默认情况下,主要文件组是默认文件组
- 可以通过
ALTER DATABASE语句修改默认文件组
4. 文件流文件组 (Filestream Filegroup)
- 用于存储 FILESTREAM 数据
- 需要单独的数据容器
- 用于存储大型二进制数据,如文档、图片和视频
页面结构
SQL Server 数据存储的基本单位是页面 (Page),每个页面的大小为 8 KB:
1. 页面类型
| 页面类型 | 描述 |
|---|---|
| 数据页 (Data Page) | 存储表数据 |
| 索引页 (Index Page) | 存储索引数据 |
| LOB 页 (LOB Page) | 存储大型对象数据 (text, ntext, image, varchar(max), nvarchar(max), varbinary(max), xml) |
| 行溢出页 (Row Overflow Page) | 存储超过 8060 字节的行数据 |
| IAM 页 (Index Allocation Map) | 跟踪区 (Extent) 的分配情况 |
| GAM 页 (Global Allocation Map) | 跟踪已分配的区 |
| SGAM 页 (Shared Global Allocation Map) | 跟踪已分配且有空闲空间的区 |
| PFS 页 (Page Free Space) | 跟踪页面的可用空间 |
| DCM 页 (Differential Changed Map) | 跟踪自上次完整备份以来修改的区 |
| BCM 页 (Bulk Changed Map) | 跟踪自上次日志备份以来使用大容量操作修改的区 |
2. 数据页结构
每个数据页包含以下部分:
- 页头 (96 字节):包含页面元数据,如页面类型、页码、对象 ID 等
- 数据行:存储实际的数据行
- 行偏移数组:存储每行数据的偏移量,从页面末尾开始向前增长
- 可用空间:页面中未使用的空间
3. 行结构
数据行包含以下部分:
- 行头:包含行状态、列计数等信息
- 列偏移数组:存储每列数据的偏移量
- 列数据:存储实际的列值
4. 区 (Extent)
区是由 8 个连续页面组成的存储单元,大小为 64 KB:
- 统一区 (Uniform Extent):由单个对象独占使用
- 混合区 (Mixed Extent):可以由多个对象共享使用(最多 8 个对象)
存储分配
SQL Server 使用以下机制管理存储分配:
1. 分配单元 (Allocation Unit)
分配单元是对象存储数据的基本单位,每个表或索引至少包含一个分配单元:
- IN_ROW_DATA:存储行内数据和非大型对象数据
- LOB_DATA:存储大型对象数据
- ROW_OVERFLOW_DATA:存储超过 8060 字节的行数据
2. 分配映射页
SQL Server 使用以下映射页跟踪存储分配:
IAM 页 (Index Allocation Map)
- 跟踪对象使用的所有区
- 每个表或索引至少有一个 IAM 页
- 存储区的分配状态
GAM 页 (Global Allocation Map)
- 跟踪数据库中所有已分配的区
- 每个 GAM 页覆盖 64,000 个区(约 4 GB)
- 每个位代表一个区,1 表示未分配,0 表示已分配
SGAM 页 (Shared Global Allocation Map)
- 跟踪已分配且有空闲空间的混合区
- 每个 SGAM 页覆盖 64,000 个区(约 4 GB)
- 每个位代表一个区,1 表示区是混合区且有空闲空间,0 表示其他情况
PFS 页 (Page Free Space)
- 跟踪页面的可用空间
- 每个 PFS 页覆盖 8,088 个页面(约 64 MB)
- 每个字节代表一个页面,记录页面的可用空间百分比
DCM 页 (Differential Changed Map)
- 跟踪自上次完整备份以来修改的区
- 用于差异备份,只备份修改的区
BCM 页 (Bulk Changed Map)
- 跟踪自上次日志备份以来使用大容量操作修改的区
- 用于日志备份,优化大容量操作的备份性能
I/O 管理
SQL Server 使用以下机制管理 I/O 操作:
1. 缓冲区管理
- 缓冲池:内存中的数据页缓存,减少磁盘 I/O 操作
- 预读:提前加载预计需要的数据页到缓冲池
- 延迟写入:异步将脏页写入磁盘,提高写入性能
- 检查点:定期将脏页写入磁盘,减少恢复时间
2. 写入机制
- 事务日志写入:同步写入,保证事务持久性
- 数据页写入:异步写入,提高写入性能
- 批量写入:合并多个小的写入操作,减少 I/O 次数
3. 读取机制
- 单页读取:读取单个页面,用于随机访问
- 预读读取:读取连续的多个页面,用于顺序访问
- 异步读取:允许在等待 I/O 完成时处理其他任务
存储优化最佳实践
1. 文件和文件组设计
- 分离数据和日志文件:将数据文件和日志文件放在不同的物理磁盘上,减少 I/O 冲突
- 使用多个数据文件:将大型表分布到多个数据文件,提高并行 I/O 性能
- 使用文件组隔离大型对象:将 LOB 数据和行溢出数据放在单独的文件组
- 考虑存储性能特性:将频繁访问的数据放在高性能存储上,将不常用的数据放在低成本存储上
2. 页面和区管理
- 避免页分裂:合理设计索引,避免频繁的页分裂操作
- 监控页面密度:定期检查页面填充度,避免碎片过多
- 使用合适的填充因子:根据数据修改频率设置合适的填充因子
- 定期重建或重组索引:减少索引碎片,提高查询性能
3. I/O 性能优化
- 使用 RAID 配置:根据性能和可靠性要求选择合适的 RAID 级别(如 RAID 10 用于数据文件,RAID 1 用于日志文件)
- 优化存储子系统:使用 SSD 存储提高 I/O 性能,合理配置存储控制器缓存
- 调整 I/O 调度策略:根据工作负载类型选择合适的 I/O 调度器
- 监控 I/O 性能:使用性能计数器和 DMV 监控 I/O 延迟和吞吐量
4. 备份和恢复优化
- 使用多个备份设备:并行备份到多个设备,提高备份速度
- 合理设置备份压缩:使用备份压缩减少备份大小和 I/O 操作
- 考虑备份位置:将备份存储在与生产数据不同的物理位置
- 优化恢复时间目标 (RTO):根据业务需求调整数据库配置,减少恢复时间
版本差异
SQL Server 不同版本在物理架构上的主要差异:
1. SQL Server 2012 及之前
- 传统的存储架构
- 有限的压缩选项
- 基本的 I/O 优化功能
2. SQL Server 2014
- 引入缓冲区池扩展 (Buffer Pool Extension),支持使用 SSD 扩展缓冲池
- 增强的备份压缩
- 改进的检查点机制
3. SQL Server 2016
- 引入 Stretch Database,将冷数据自动迁移到 Azure Blob 存储
- 增强的行级压缩和页级压缩
- 改进的存储引擎性能
4. SQL Server 2017
- 跨平台支持,支持在 Linux 上运行
- 增强的 TempDB 性能
- 改进的 I/O 子系统
5. SQL Server 2019
- 引入持久化内存 (PMEM) 支持,提高 I/O 性能
- 增强的 Columnstore 索引性能
- 改进的批量导入性能
6. SQL Server 2022
- Azure Synapse Link 集成,支持直接查询 Azure Synapse Analytics
- 增强的 Always On 可用性组存储性能
- 改进的智能查询处理,减少 I/O 操作
监控和维护
1. 监控存储使用情况
使用 DMV 监控:
sys.dm_db_file_space_usage:监控数据库文件空间使用情况sys.dm_db_index_physical_stats:监控索引碎片情况sys.dm_io_virtual_file_stats:监控文件 I/O 统计信息
使用性能计数器监控:
SQLServer:Databases计数器:监控数据库大小和增长情况PhysicalDisk计数器:监控磁盘 I/O 性能LogicalDisk计数器:监控逻辑磁盘空间使用情况
2. 维护任务
- 定期备份数据库:确保数据安全,支持恢复
- 重建或重组索引:减少索引碎片,提高查询性能
- 更新统计信息:确保查询优化器有准确的统计信息
- 检查数据库完整性:使用
DBCC CHECKDB检查数据库完整性 - 监控和清理事务日志:避免事务日志过大导致的问题
常见问题 (FAQ)
Q: 如何确定数据库文件的最佳大小?
A: 确定数据库文件最佳大小的方法包括:
- 分析历史数据增长趋势
- 考虑业务增长预期
- 避免频繁的自动增长操作(设置合适的初始大小和增长增量)
- 监控文件空间使用情况,及时调整大小
Q: 如何优化事务日志性能?
A: 优化事务日志性能的方法包括:
- 将事务日志放在单独的物理磁盘上
- 使用合适的 RAID 级别(如 RAID 1 或 RAID 10)
- 避免过度的事务日志增长(设置合适的恢复模式和备份策略)
- 优化写入密集型应用,减少事务大小和频率
Q: 什么是页分裂,如何避免?
A: 页分裂是指当页面空间不足时,SQL Server 将页面分裂为两个页面的操作。避免页分裂的方法包括:
- 使用合适的填充因子,为数据增长预留空间
- 合理设计索引,避免在递增键上的频繁插入
- 定期重建或重组索引
- 避免在索引列上进行大量更新操作
Q: 如何监控和减少索引碎片?
A: 监控和减少索引碎片的方法包括:
- 使用
sys.dm_db_index_physical_statsDMV 监控碎片情况 - 当碎片率在 5%-30% 之间时,使用
ALTER INDEX REORGANIZE重组索引 - 当碎片率超过 30% 时,使用
ALTER INDEX REBUILD重建索引 - 考虑使用在线重建索引,减少对业务的影响
Q: 如何优化 TempDB 性能?
A: 优化 TempDB 性能的方法包括:
- 创建多个 TempDB 数据文件,数量等于或略少于 CPU 核心数
- 确保所有 TempDB 数据文件大小相同,避免文件自动增长
- 将 TempDB 放在高性能存储上
- 监控 TempDB 使用情况,避免过度使用
- 优化需要大量 TempDB 空间的查询
Q: 什么是 CHECKDB,何时应该运行?
A: DBCC CHECKDB 是用于检查数据库完整性的命令,包括:
- 检查数据库对象的逻辑和物理完整性
- 检查索引和数据页的一致性
- 检查系统表的完整性
建议定期运行 DBCC CHECKDB,频率取决于数据库的重要性和修改频率,通常每周或每月运行一次。对于大型数据库,可以考虑使用 PHYSICAL_ONLY 选项减少运行时间。
总结
SQL Server 物理架构是数据库性能和可靠性的基础,了解物理架构有助于 DBA 优化存储设计、提高 I/O 性能和确保数据安全。通过合理设计文件和文件组、优化页面和区管理、调整 I/O 子系统配置,DBA 可以显著提高 SQL Server 数据库的性能和可靠性。
同时,定期监控存储使用情况、执行维护任务和优化存储配置,也是确保 SQL Server 数据库长期稳定运行的关键。随着存储技术的不断发展(如 SSD、持久化内存等),DBA 需要不断学习和适应新的存储技术,以充分利用硬件优势,提高数据库性能。
