本节摘要:逻辑设计管"存什么",物理设计管"怎么存"。本节讲清楚存储引擎选择、表空间/页/块设计、数据压缩、字符集,从物理层提性能。
不同存储引擎适合不同场景:
MySQL InnoDB(默认):
MySQL MyISAM(老引擎):
PostgreSQL:
列式存储(OLAP):
选择:OLTP 用行存(InnoDB/PostgreSQL),OLAP 用列存(ClickHouse/Doris),混合用 HTAP(TiDB/CockroachDB)。
表空间(Tablespace):逻辑存储单元,管理数据文件。
1. 系统表空间 vs 独立表空间
2. 表空间分离
3. 临时表空间
数据库以页(page/block)为单位读写,页大小影响性能:
1. 页大小权衡
2. 默认与配置
3. 选择
压缩省空间、提缓存命中率(同样内存存更多数据),但增加 CPU:
1. InnoDB 压缩
2. 列存压缩
3. 表级压缩
权衡:IO 瓶颈用压缩(减 IO 换 CPU),CPU 瓶颈不用。压缩数据解压增加延迟,延迟敏感慎用。
字符集:影响存储空间和比较性能。
1. utf8 vs utf8mb4
2. 排序规则(Collation)
3. 字符集影响索引
InnoDB 行格式:
选择:默认 DYNAMIC 即可,大字段表用 DYNAMIC 避免行膨胀。压缩看场景。
1. Redo Log
2. Binlog
3. Undo Log
⚠️ 常见误读:以为"压缩总是好"。压缩省空间提缓存,但增 CPU 和延迟。IO 瓶颈受益,CPU 瓶颈或延迟敏感慎用。
💡 关键直觉:物理设计——存储引擎(OLTP 行存 InnoDB/PG,OLAP 列存 ClickHouse/Doris 压缩高,HTAP TiDB)、表空间(独立 file_per_table 单表可优化、分离磁盘并行 IO 热冷分盘、临时表空间)、页大小(OLTP 小页 8/16KB 随机快,OLAP 大页 32/64KB 顺序快+大页降 TLB miss)、压缩(InnoDB COMPRESSED zlib/列存 RLE 字典 Delta 10:1/冷数据,IO 瓶颈用换 CPU,CPU 瓶颈不用)、字符集(utf8mb4 完整 Unicode/排序规则 _ci 不敏感 _bin 快)、行格式(DYNAMIC 大字段溢出页避免行膨胀)、日志优化(Redo 大减 checkpoint 放 SSD/Binlog sync_binlog 折中/Undo 独立表空间)。
物理层的核心概念"页"值得量化展开。数据库按页(通常八或十六KB)读写磁盘,一行数据在页内的填充度决定了三个关键行为:空间利用率(半满的页浪费一半 IO 带宽在读空气上)、写入放大(随机插入导致页分裂,一次逻辑写变成"分裂两页加标记旧页"三次物理写)、碎片整理收益(重建索引恢复填充度后,扫描同样数据的 IO 次数下降)。量化感觉:一亿行的表,页填充从九成跌到六成,全表扫描的物理读次数增加一半,缓冲池里能装下的有效数据减少三分之一——同一个查询变慢的物理根源就在这。应对策略分主动与被动:设计期用自增主键让插入天然有序(减少分裂)、批量导入前后控制填充参数;运维期定期检测碎片率、在低峰窗口重建。理解页的行为后你会重新看待很多"玄学"现象——为什么重建索引后变快了、为什么随机 UUID 主键的表越用越慢、为什么监控里"写 IO 远大于业务写入量"——它们都是同一门"页物理学"的不同切面。
物理层还有一个常被低估的杠杆:数据压缩。它的收益逻辑是三重的——空间省(典型列压缩比三到五倍,存储成本直降)、IO 省(同样一页装下更多行,扫描与缓冲命中率同步受益——这是最主要的性能收益)、缓冲池等效放大(内存里能驻留的有效数据多了数倍,热工作集的定义被改写)。代价同样明确——CPU 升(压缩解压耗计算,CPU 已经是瓶颈的系统慎用)、更新成本(高频更新的页反复重压缩,写放大叠加)。适用判断的三问:数据是不是读多写少(报表与历史库:用,没有理由不用)、CPU 是否有余量(CPU 空闲而 IO 紧张:用,这是最优的交易)、压缩算法是否可选(按列选算法:字符列与数字列各取所需)。一个反直觉的实战现象值得记住:某些全表扫描型查询开启压缩后反而更快——省下的 IO 时间超过了压缩解压的 CPU 时间,这笔"用计算换带宽"的交易在存储受限的环境里几乎稳赚。压缩是物理层给预算有限的团队准备的免费午餐,漏掉它常常是因为不知道菜单上有这道菜。
物理层给一个实操性极强的动作:行宽体检。体检方法:对核心表统计平均行宽(理论宽度与实际占用),对照缓冲池大小算"一页能装几行、热区数据要几页、缓冲池能驻留几成"——这组数字直接决定了缓存效率的天花板。瘦身的四个动作:动作一,大字段外迁(详情文本、长备注移到扩展表,主表瘦身);动作二,历史字段归档化(只在报表用的列移到归档表);动作三,字段顺序与空值优化(可空列与变长列的物理布局影响实际占用,部分引擎对定长与变长的处理差异值得利用);动作四,压缩启用(第 6 小节的杠杆)。瘦身的收益模型:行宽减三成,同样的缓冲池多装四成的行、同样的 IO 带宽多搬四成的数据——等效于免费扩了内存与存储带宽。行宽是设计期决策、运维期发现的最典型项:体检动作的意义就是把发现提前到还来得及瘦的时候。
物理章收官给两个可以直接引用的经验数值(附适用条件)。数值一,页的半满阈值:核心表的页平均填充度低于六成时,扫描类查询的 IO 浪费开始可感(四成的空间在搬空气),碎片治理的优先级上调——低于五成就是明确的行动信号。数值二,行宽的舒适区:OLTP 高频表的平均行宽控制在几百字节内(考虑索引后的整行访问成本),超过一千字节就该评估大字段外迁——行宽翻倍近似等于热数据容量翻倍的内存压力。两个数值的适用边界:它们是"开始思考的阈值"而非"必须行动的红线"——具体行动要结合扫描频率与内存余量综合判断;但有了阈值,巡检时的"看一眼就知道有没有事"就成了可能。经验数值是老工程师的压缩饼干——不精致但顶饿,用的时候配上一杯"自己环境验证"的水。
补一句与大表治理的衔接:物理层的瘦身(行宽、压缩)与第 5 章的归档是互补的两条腿——归档解决"不需要的数据还占着地方",瘦身解决"需要的数据占得太多";治理大表的完整方案通常两条腿都要走,先后顺序按痛点定(扫描慢先瘦身、存储贵先归档)。两章配合读,大表治理的兵器谱就齐了。
再补一个存储引擎选择的提醒:同库多引擎的场景(部分数据库支持),物理层的优化要按引擎分区施策——行存引擎的页优化逻辑(本节内容)不适用于列存区域(列存按列压缩、按块读取,优化重心在排序键与压缩算法);混合负载系统里给"事务热区用行存、分析冷区用列存"的分区方案,正在成为大数据量场景的主流选择——这其实是第 5 章冷热分离思想在物理层的提前落地,两章合读,效果最好。
收尾再点一个与监控的衔接:物理层的健康要进仪表盘的三个数字——页平均填充率、行宽分布、缓冲命中率(按表分解)——它们是物理设计的体检指标,也是本节所有优化动作的效果度量;没有这三个数字的物理优化是盲动,有了它们,物理层就从"设计时的一次性功夫"变成了"运行期的持续资产"。