Files
hospital_performance/.qoder/repowiki/zh/content/数据库设计/表结构设计/索引与约束设计.md
2026-02-28 15:16:15 +08:00

18 KiB
Raw Blame History

索引与约束设计

**本文引用的文件** - [models.py](file://backend/app/models/models.py) - [finance.py](file://backend/app/models/finance.py) - [001_initial.py](file://backend/alembic/versions/001_initial.py) - [002_template.py](file://backend/alembic/versions/002_template.py) - [database.py](file://backend/app/core/database.py) - [config.py](file://backend/app/core/config.py) - [database.md](file://docs/database.md) - [init_db.py](file://backend/init_db.py)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考量
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件聚焦于该医院绩效系统的数据库索引与约束设计,系统采用 SQLAlchemy ORM + Alembic 进行模型定义与迁移,结合 PostgreSQL 异步驱动,围绕“科室—员工—考核—指标—工资—计划—模板—菜单—财务”等核心业务实体,系统化梳理主键、外键、唯一索引、复合索引、检查约束的设计原则与性能影响,并给出查询优化建议与并发控制考虑。

项目结构

  • 数据模型集中于 models 目录,通过 Base 声明式基类统一建模。
  • Alembic 版本化迁移文件定义了初始表结构与索引。
  • 配置模块提供数据库连接参数与池化配置。
  • 文档目录包含数据库 ER 图与表结构说明。
graph TB
subgraph "模型层"
M1["models.py<br/>核心业务模型"]
M2["finance.py<br/>财务核算模型"]
end
subgraph "迁移层"
V1["001_initial.py<br/>初始版本"]
V2["002_template.py<br/>模板扩展"]
end
subgraph "运行时"
C["config.py<br/>配置"]
D["database.py<br/>引擎/会话"]
I["init_db.py<br/>初始化脚本"]
end
subgraph "文档"
DOC["database.md<br/>ER图与表说明"]
end
M1 --> V1
M2 --> V2
V1 --> D
V2 --> D
C --> D
I --> D
DOC -.参考.-> M1

图表来源

章节来源

核心组件

  • 主键与自增:多数表使用整型自增主键,确保全局唯一性与插入性能。
  • 外键约束:通过 ForeignKey 映射,形成稳定的父子关系与引用完整性。
  • 唯一约束:对业务唯一字段(如科室编码、员工工号、指标编码、用户名、模板编码)施加唯一约束,避免重复。
  • 索引策略:针对高频过滤/连接/排序字段建立单列索引;对多条件组合查询建立复合索引;对枚举字段建立索引提升筛选效率。
  • 检查约束:对数值范围进行约束(如权重>0、金额>=0保证数据质量与业务规则一致性。

章节来源

架构总览

系统采用分层架构ORM 层负责模型映射与约束声明,迁移层负责表结构演进,运行时提供异步连接与会话管理。

graph LR
A["前端(Vue)"] --> B["后端(FastAPI)"]
B --> C["服务层"]
C --> D["ORM(SQLAlchemy)"]
D --> E["数据库(PostgreSQL)"]
D --> F["索引/约束"]

图表来源

详细组件分析

科室表departments

  • 主键id自增
  • 唯一索引code科室编码
  • 单列索引dept_type按类型过滤、parent_id树形结构查询
  • 外键parent_id 自引用(树形组织)
  • 设计要点dept_type 用于快速筛选不同类型的科室parent_id 支持层级查询code 唯一保证业务唯一性。
erEntity
"departments" {
id : integer PK
code : varchar(20) UK
dept_type : enum
parent_id : integer FK
level : integer
sort_order : integer
is_active : boolean
created_at : datetime
updated_at : datetime
}

图表来源

章节来源

员工表staff

  • 主键id自增
  • 唯一索引employee_id工号
  • 单列索引department_id按科室统计/查询、status按状态筛选
  • 外键department_id → departments.id
  • 设计要点department_id 与 status 的索引支持按科室聚合与状态筛选unique 约束保证工号唯一。
erEntity
"staff" {
id : integer PK
employee_id : varchar(20) UK
department_id : integer FK
status : enum
created_at : datetime
updated_at : datetime
}

图表来源

章节来源

考核指标表indicators

  • 主键id自增
  • 唯一索引code指标编码
  • 单列索引indicator_type按类型筛选
  • 检查约束weight > 0权重必须为正数
  • 设计要点:唯一编码保证业务唯一;按类型索引支持快速筛选;检查约束保证权重合法性。
erEntity
"indicators" {
id : integer PK
code : varchar(20) UK
indicator_type : enum
weight : numeric(5,2)
created_at : datetime
updated_at : datetime
}

图表来源

章节来源

考核记录表assessments

  • 主键id自增
  • 单列索引staff_id按员工查询、status按状态筛选
  • 复合索引period_year + period_month按年月组合查询
  • 外键staff_id → staff.idassessor_id/reviewer_id → staff.id自关联
  • 设计要点复合索引支持按年月快速定位staff_id 索引支撑员工维度统计status 索引便于流程状态筛选。
erEntity
"assessments" {
id : integer PK
staff_id : integer FK
period_year : integer
period_month : integer
status : enum
assessor_id : integer FK
reviewer_id : integer FK
created_at : datetime
updated_at : datetime
}

图表来源

章节来源

考核明细表assessment_details

  • 主键id自增
  • 单列索引assessment_id按考核记录查询明细、indicator_id按指标查询明细
  • 外键assessment_id → assessments.idindicator_id → indicators.id
  • 设计要点:双外键字段分别建立单列索引,满足“按记录查明细”和“按指标查明细”的常见查询模式。
erEntity
"assessment_details" {
id : integer PK
assessment_id : integer FK
indicator_id : integer FK
created_at : datetime
updated_at : datetime
}

图表来源

章节来源

工资核算表salary_records

  • 主键id自增
  • 单列索引staff_id按员工查询、status按状态筛选
  • 复合索引period_year + period_month按年月组合查询
  • 外键staff_id → staff.id
  • 设计要点复合索引支持按年月快速检索staff_id 索引支撑员工维度统计。
erEntity
"salary_records" {
id : integer PK
staff_id : integer FK
period_year : integer
period_month : integer
status : varchar(20)
created_at : datetime
updated_at : datetime
}

图表来源

章节来源

用户表users

  • 主键id自增
  • 唯一索引username用户名
  • 外键staff_id → staff.id可选关联
  • 设计要点username 唯一索引支持登录认证staff_id 外键实现用户与员工的弱关联。
erEntity
"users" {
id : integer PK
username : varchar(50) UK
staff_id : integer FK
created_at : datetime
updated_at : datetime
}

图表来源

章节来源

绩效计划表performance_plans

  • 主键id自增
  • 唯一索引plan_code计划编码
  • 单列索引plan_level、plan_year、department_id、status
  • 外键department_id → departments.idstaff_id → staff.idsubmitter_id/approver_id → users.idparent_plan_id → performance_plans.id自关联
  • 设计要点:多维索引支持按层级、年份、状态、科室等条件筛选;唯一编码保证业务唯一性。
erEntity
"performance_plans" {
id : integer PK
plan_code : varchar(50) UK
plan_level : enum
plan_year : integer
department_id : integer FK
status : enum
parent_plan_id : integer FK
created_at : datetime
updated_at : datetime
}

图表来源

章节来源

计划-指标关联表plan_kpi_relations

  • 主键id自增
  • 单列索引plan_id、indicator_id
  • 复合唯一索引plan_id + indicator_id唯一关联
  • 外键plan_id → performance_plans.idindicator_id → indicators.id
  • 设计要点:复合唯一索引防止重复关联;单列索引支撑按计划或指标查询。
erEntity
"plan_kpi_relations" {
id : integer PK
plan_id : integer FK
indicator_id : integer FK
plan_id+indicator_id : unique
created_at : datetime
updated_at : datetime
}

图表来源

章节来源

模板-指标关联表template_indicators

  • 主键id自增
  • 单列索引template_id、indicator_id
  • 复合唯一索引template_id + indicator_id唯一关联
  • 外键template_id → indicator_templates.idindicator_id → indicators.id
  • 设计要点:与计划-指标关联一致的索引策略,确保模板维度的高效查询。
erEntity
"template_indicators" {
id : integer PK
template_id : integer FK
indicator_id : integer FK
template_id+indicator_id : unique
created_at : datetime
updated_at : datetime
}

图表来源

章节来源

财务核算表department_finances

  • 主键id自增
  • 单列索引department_id、finance_type、category
  • 复合索引period_year + period_month按年月组合查询
  • 检查约束amount >= 0金额非负
  • 外键department_id → departments.id
  • 设计要点:多维索引支持按科室、类型、类别、期间的高效查询;检查约束保证财务数据的正向性。
erEntity
"department_finances" {
id : integer PK
department_id : integer FK
period_year : integer
period_month : integer
finance_type : enum
category : varchar(50)
amount : numeric(12,2)
created_at : datetime
updated_at : datetime
}

图表来源

章节来源

依赖关系分析

  • 模型层通过 table_args 声明索引与约束,迁移层通过 Alembic 在数据库层面落地。
  • 外键关系形成稳定的层次结构(如 departments 树形、assessments 与 staff 的自关联)。
  • 初始化脚本在首次启动时创建表结构并注入基础数据。
graph TB
subgraph "模型定义"
MD["models.py"]
MF["finance.py"]
end
subgraph "迁移执行"
MI["001_initial.py"]
MT["002_template.py"]
end
subgraph "运行时"
DB["database.py"]
CFG["config.py"]
INIT["init_db.py"]
end
MD --> MI
MF --> MT
MI --> DB
MT --> DB
CFG --> DB
INIT --> DB

图表来源

章节来源

性能考量

  • 索引选择原则
    • 单列索引:适用于等值/范围查询的过滤字段(如 status、dept_type、indicator_type
    • 复合索引:适用于多条件组合查询(如 assessments 的 period_year + period_monthsalary_records 的 period_year + period_monthfinance 的 period_year + period_month
    • 唯一索引保证业务唯一性code、employee_id、username、plan_code、模板-指标唯一组合)。
  • 查询优化建议
    • 使用复合索引覆盖多条件过滤,减少回表与排序开销。
    • 对枚举字段建立索引,提升 IN/等值过滤效率。
    • 尽量避免 SELECT *,仅选择必要列,降低 IO。
    • 对大表的分页查询配合 ORDER BY + LIMIT确保 ORDER BY 列命中索引。
  • 并发控制
    • 使用数据库事务隔离级别与锁策略,避免写放大与死锁。
    • 对高并发写入场景,合理拆分热点表或引入分区(如按年/月分区)。
    • 控制批量写入批次大小,避免长事务占用资源。
  • 数据完整性
    • 外键约束保证引用完整性;唯一约束保证业务唯一性;检查约束保证数值范围合法。
    • 在 ORM 层与数据库层双重约束,确保数据一致性。

[本节为通用性能指导,不直接分析具体文件]

故障排查指南

  • 索引未生效
    • 检查查询条件是否与索引列顺序匹配(复合索引前缀匹配)。
    • 使用 EXPLAIN/ANALYZE 分析执行计划,确认索引扫描路径。
  • 唯一冲突
    • 当插入重复唯一键时,捕获数据库异常并提示用户修正(如重复工号、重复指标编码)。
  • 外键约束失败
    • 确认被引用记录存在且状态有效;检查删除/更新策略RESTRICT/CASCADE/SET NULL
  • 检查约束失败
    • 校验输入数据是否满足约束条件(如权重>0、金额>=0在业务层提前校验减少数据库往返。

[本节为通用排查建议,不直接分析具体文件]

结论

该系统在索引与约束设计上遵循“业务唯一性优先、高频查询覆盖、枚举与复合索引配合”的原则,结合外键与检查约束,有效保障了数据完整性与查询性能。建议在后续迭代中持续关注查询执行计划与热点表,适时引入分区与物化视图,进一步提升大规模数据下的响应能力。

[本节为总结性内容,不直接分析具体文件]

附录

  • 数据库连接与池化配置
    • 数据库 URL、连接池大小与溢出配置确保高并发下的稳定性。
  • 初始化脚本
    • 首次启动自动创建表结构并注入基础数据,便于开发与测试环境快速就绪。

章节来源