SQL Server千万级题库父子关系表结构最优设计方案咨询
百万级带层级关系的SQL Server题库表结构选型
需求背景
需设计支持子题层级关系的题库表结构,数据规模超1000万条,采用SQL Server作为存储介质。题目核心属性包括:qid(题号)、stem(题干)、qtype(题型)、解析、answer(答案)等。
三种候选方案
方案一:单表邻接表模式
所有题目(含父题、子题)存储在同一张表中,通过parentId关联父题:
"Question" 表 ============================================================ qid | parentId | qtype | stem | answer | childQty | 其他字段.. ============================================================
方案二:父题与子题分表存储
父题和子题分别存入两张独立表,子题通过qid关联对应父题:
"Question" 表(仅存父题) =============================================== qid | qtype | stem | answer | childQty | 其他字段.. ============================================== "SubQuestion" 表(仅存子题) ============================================= subid | qid | qtype | stem | answer | 其他字段.. =============================================
方案三:单表存所有题目+独立关系表维护层级
所有题目统一存储在Question表,通过单独的关系表维护父子题关联:
"Question" 表(存储所有题目) ================================================= qid | qtype | stem | answer | childQty | 其他字段.. ================================================= "QuestionRelationships" 表(维护父子关系) ============= qid | subid =============
方案选型结论:优先选择方案三
针对1000万级数据量和SQL Server的特性,方案三是最优选择,理由如下:
- 数据一致性与扩展性更强:所有题目属性统一在Question表维护,避免方案二中父子题表结构冗余、修改不同步的问题;后续新增题目属性只需修改一张表,适配业务变化更灵活。
- 查询性能更优:SQL Server对大表索引优化支持成熟,Question表可针对
qid、qtype等字段建立高效索引;关系表结构极简,可建立(qid, subid)联合主键或双向索引,层级查询(如查某父题的所有直接子题、某子题的父级)时,关联查询效率远高于方案一的递归CTE(邻接表在百万级数据下递归性能会急剧下降)。 - 冗余控制更合理:方案一的
parentId字段会存在大量NULL值(顶级父题),造成字段冗余;方案三通过独立关系表维护关联,避免了单表冗余;方案二的两张表字段重复,维护成本高。 - 适配复杂层级场景:如果后续业务扩展到多级子题(父→子→孙),方案三只需在关系表新增关联记录即可,无需修改表结构;方案一的递归查询性能会随层级加深暴跌,方案二则完全无法支持多级结构。
额外优化建议
- Question表的
qid建议使用BIGINT自增类型,避免INT类型的存储溢出; - 给QuestionRelationships表建立
(qid, subid)联合主键,同时新增(subid, qid)反向索引,方便快速查询子题的父级; - 若高频查询某父题的直接子题数量,可保留Question表的
childQty字段作为冗余,但需通过触发器或业务逻辑确保该字段值的准确性。
内容的提问来源于stack exchange,提问作者Colin Chen
相关产品推荐
相关产品推荐

