大家好,我是小耶,写功课只是为了我踩过的坑,你们别再踩了!
做DBA久了,你一定会遇到这种情况:一张表有十几个索引,一半是重复的。一个存储过程两千行,改了三个月不敢动。数据库迁移评估下来,发现80%的工作量在"处理历史包袱"。
这就是数据库技术债务。它比代码的技术债务更隐蔽------代码债在IDE里能看见,数据库债藏在执行计划、表结构、存储过程、数据模型里,平常不觉得有问题,一旦要动,代价极其高昂。
技术债的产生,从来不是因为开发者偷懒或选错了技术栈,而是那些"当时看起来合理"的小决策在业务迭代中不断发酵、滚雪球,最终演变成无法收拾的大问题。今天从数据架构的角度,把数据库技术债务拆开讲一遍。
一、数据库技术债务的四种类型
1. 索引债:冗余与缺失并存
一张表十几个索引,有些重复、有些从来没用过。每次写入都要维护所有索引,性能白白消耗。
识别方法:
bash
-- 查找冗余索引(MySQL)
SELECT * FROM sys.schema_redundant_indexes;
-- 查找未使用的索引(需要开启performance_schema)
SELECT * FROM sys.schema_unused_indexes;
2. 表结构债:字段含义模糊、耦合混乱
字段名跟业务含义对不上、一张表承担了多种职责、枚举值散落在代码里没有统一管理。更隐蔽的是"字段膨胀"------一张表为了兼容不同业务版本,不断加字段,从20列变成80列,查询时SELECT *拖回大量无用数据。
3. 存储过程/函数债:业务逻辑"锁"在数据库里
几千行的存储过程,没有人敢改。业务逻辑与数据库强耦合,更换数据库时全部要重写。某团队在Oracle迁移评估中发现,迁移工作量的70%来自存储过程改写,而核心业务逻辑只占30%。
4. 数据模型债:模型与业务语义脱节
这是最深层也最难偿还的债务。数据库模型是五年前设计的,业务已经迭代了十几个版本,模型还在描述五年前的业务。查询变得越来越复杂,ETL逻辑越来越绕,新的需求需要绕开模型才能实现。
二、技术债务的累积机制
技术债务不是一次产生的,而是被无数个"当时看起来合理"的小决策堆出来的:
-
项目初期:"先上线再说,后面再优化"------然后没有"后面"
-
业务迭代:"这个字段先加在这里,以后单独建表"------"以后"永远不会来
-
性能优化:"先加个索引,等有空再整理"------索引越来越多,没人整理
-
人员变动:最了解这张表的人离职了,新来的人不敢动
这些决策本身没问题,问题在于"没有人回头看"。债务在累积,但没有人在记账。
三、如何识别和评估技术债务
第一步:建立债务清单
| 债务类型 | 识别方法 | 量化指标 |
|---|---|---|
| 索引债 | sys.schema_redundant_indexes |
冗余索引数量、未使用索引占比 |
| 表结构债 | 表字段数量、字段注释完整度 | 平均字段数、NULL比例、缺少注释的字段数 |
| 存储过程债 | 存储过程代码行数、调用链复杂度 | 平均行数、嵌套层级、依赖深度 |
| 数据模型债 | 业务变更频率 vs 模型变更频率 | 模型最后更新时间、与当前业务匹配度 |
第二步:评估偿还优先级
不是所有债务都需要立即偿还。用两个维度评估:
-
影响范围:这个债务影响了多少业务?核心交易链路 vs 内部报表
-
偿还成本:还这笔债需要多少工作量?改索引 vs 重构数据模型
高影响+低成本 = 立即偿还。低影响+高成本 = 列入长期规划。
四、偿还策略:渐进式重构
技术债务最大的陷阱是"要么不动,要么推倒重来"------前者让债务继续累积,后者风险太高。正确的策略是渐进式重构。
策略一:索引债------定期清理
-
每月运行一次
sys.schema_redundant_indexes,标记冗余索引 -
先标记为
INVISIBLE(MySQL 8.0),观察一周,确认没有查询使用后再删除
策略二:表结构债------增量拆分
不要一次性拆表,而是:
-
新业务用新表结构
-
旧业务逐步迁移到新表
-
彻底下线旧表
策略三:存储过程债------分层剥离
存储过程债的偿还核心是把业务逻辑从数据库层向上迁移:
-
新需求不再写存储过程,改在应用层实现
-
存量存储过程按调用频率排序,高频的优先重写
-
低频的可暂时保留,逐步淘汰
策略四:数据模型债------建立防腐层
当数据模型与业务语义脱节时,不要直接改表结构(影响面太大)。在应用层建立一层"防腐层"(Anti-Corruption Layer),把旧模型映射到新语义上,新业务只面向新语义开发。等旧业务全部迁移完成后,再考虑改表结构。
五、从"管数据库"到"管数据架构"
DBA和数据架构师的核心区别,在于时间视角和关注范围:
| 维度 | DBA | 数据架构师 |
|---|---|---|
| 时间视角 | 当下(今天的问题今天解决) | 未来(三年后这套架构还能不能扛) |
| 关注范围 | 单个数据库实例 | 整个数据体系 |
| 债务态度 | 处理眼前的债务 | 预防未来的债务 |
技术债务的化解,离不开技术理念的持续突破与底层范式的革新。数据架构师的核心职责之一,就是在债务累积到不可收拾之前,识别它、评估它、有计划地偿还它。
六、总结
数据库技术债务比代码技术债务更难发现、更难偿还。但它不是不可管理的------把它当作一种"架构风险"来对待,而不是"历史包袱"来逃避。
四个关键认知:
-
债务是积累的,不是一次产生的------每一次"先上线再说"都在增加债务
-
债务需要记账------建立债务清单,定期审查
-
债务需要分级------不是所有债务都要立即还,按影响范围和成本排优先级
-
债务需要渐进偿还------不要推倒重来,用增量方式逐步消除
从DBA到数据架构师,核心的跃迁不是技术深度的增加,而是时间视角的拉长和关注范围的扩大。当你的注意力从"今天怎么修"扩展到"三年后怎么不坏"的时候,你已经在做数据架构师的工作了。
小耶在手,SQL 不愁
还有什么想了解的,欢迎留言!小耶一定知无不言言无不尽......我们下次见~