AzerothCore学习笔记·数据库05:模板表设计——核心字段演化逻辑

发布时间:2026/6/11 22:38:04

AzerothCore学习笔记·数据库05:模板表设计——核心字段演化逻辑 数据库设计课上有一条铁律宽表是坏味道。字段多到几十上百行不同类型的实体挤在同一张表里——这是反范式是设计缺陷是迟早要还的技术债。然后你去看 AzerothCore 的item_template接近两百个字段creature_templateitem_entry表有 50 字段外加creature_template本身 100 字段。两张核心表每张都宽到离谱。为什么答案要从 WoW 里到底有多少种东西说起。一个表要描述多少种东西AzerothCore 里有 25000 种怪物20000 种物品。这 25000 种怪物差异极大有的会施法有的不会有的是人形有的是亡灵有的是机械有的掉金币有的不掉。如果严格按范式设计应该拆成creature_template_basecreature_template_spellscreature_template_lootcreature_template_ai…… 拆十几张表每种怪物只填充其中几张。问题是查询时要 JOIN 十几张表。怪物数据在游戏里是高频读取的——每只怪刷新时都要读模板。JOIN 十几张表在 MMO 这种高并发场景下性能代价是不可接受的。物品的情况更极端。武器有伤害和速度消耗品有使用效果和冷却任务物品要关联任务ID配方有技能要求——每种物品类型的字段集合完全不同。如果按类型拆表item_template_weaponitem_template_armoritem_template_consumable…… 光是物品类型就有几十种查询时要不 JOIN 很多表要不写复杂的 UNION。creature_template 的字段分类宽表不是乱放。两百多个字段拆开看分几大类基础属性entry模板ID、name名称、faction阵营、npcflagNPC功能标志战斗属性mindmg/maxdmg伤害范围、attackpower、health/mana、armor模型相关modelid1~4模型ID最多4个用于随机选模型、HealthModifier/ManaModifierAI相关AINameAI类型NullAI、ReactorAI、PassiveAI、AggressorAI……、ScriptName掉落相关lootid掉落表ID、pickpocketloot偷窃掉落、skinloot剥皮掉落其他spell施放的法术列表、movement巡逻路径类型、种族/职业限制主要对玩家生效的NPC大部分字段对大部分怪物来说是 NULL 或默认值但它们都在同一张表里。拿一个具体例子一只普通森林狼modelid117550mindmg9maxdmg13spell0AINameNullAI——其余字段全是 NULL。但查这只狼时一次 SELECT * 搞定不用 JOIN 五张表。宽表的取舍空间换时间AzerothCore 的选择一个表所有字段用 NULL 表示这个字段对我无效。好处很明显一次 SELECT * 就能拿到这只怪物的全部数据不需要 JOIN。磁盘空间便宜CPU 和延迟贵——对于 MMO 服务端这是正确的取舍。字段是怎么长出来的item_template和creature_template的字段不是一次性设计好的而是随着 WoW 的每一次资料片逐步加出来的。原版2004基础字段——名字、等级、属性燃烧的远征2007加了韧性、法术穿透巫妖王之怒2008加了成就相关字段大地的裂变2010加新种族/职业兼容后续资料片持续加新字段……如果去看creature_template的字段列表会发现一些奇怪的字段——只对某个资料片的某种怪物有意义但字段留在表里没人删。删字段是破坏性操作所有已有的 template 数据都要迁移成本远高于留着几个 NULL 字段。这不是设计懒惰而是演化式架构的必然结果系统活着需求在变表结构只能加很难减。dbdocs字段级的文档系统字段越来越多新人看表结构会完全懵掉——这个字段是干嘛的默认值是多少AzerothCore 在data/sql/dbdocs/目录下给 World 库每一张表的每一个字段写说明。如果你想知道creature_template里AIName字段取什么值、是什么意思直接查 dbdocs不用翻代码或猜。数据库 schema 本身不包含业务语义。AIName的值是字符串“NullAI”、“PassiveAI”、“AggressorAI”……这些字符串的含义只能在文档里说清楚。dbdocs 把这件事系统化了每个字段有中文说明、取值范围、默认值、联动关系。对于 World 库这种配置驱动的库来说这比写再多代码注释都管用。为什么 Characters 库的表反而窄回过头看characters主表大概 50 个字段character_inventory只有 10 个左右。原因很简单Characters 库里的每张表描述的是一个明确、稳定的概念。角色这个概念不会突然多出十几个新维度背包里有个物品这个关系也很稳定。World 库的模板表描述的是游戏内容——这是会持续膨胀的。每一次资料片加入新机制都可能在模板表里加字段。这就是「配置」和「状态」在表设计上的根本差异配置表跟着游戏内容走只会越来越多状态表跟着玩家行为走结构是稳定的。回到开头的悖论数据库课说宽表是坏味道MMO 场景说宽表是正确选择。两者都对——因为场景不同取舍就不同。AzerothCore 的模板表设计本质上是对读多写少、配置驱动、容忍 NULL、拒绝 JOIN这四个原则的正确执行。这套取舍同样体现在 AzerothCore 的条件系统里——下篇聊的conditions表是 World 库里最精巧的一张表。

相关新闻