YOJ·数据库设计

数据库表设计

用户表

user

列名 数据类型 约束 备注
id bigint primary key auto_increment, 用户id
user_account varchar(256) unique 账号
user_password varchar(512) 密码
user_avatar varchar(1024) 用户头像uri
user_name varchar(256) 用户昵称
user_role varchar(256) 用户角色:user/admin
create_time datetime 创建时间
update_time datetime 更新时间
is_delete tinyint 是否删除,0-正常、1-删除

题目表

question

列名 数据类型 约束 备注
id bigint primary key 题目id
title varchar(512) 标题
content text 内容
user_id bigint 创建用户 id
difficulty tinyint 难度,1-简单、2-中等、3-困难
tags varchar(1024) 标签列表(json 数组)
submit_num int 题目提交数
accepted_num int 题目通过数
code_template int 代码模板,0-default、>0-核心代码模式的特定模板id
judge_mode tinyint 判题模式,1-普通评测、2-特殊评测 (未开放)
judge_cases text 判题用例(json 对象数组)
judge_config text 判题配置(json 对象)
create_time datetime 创建时间
update_time datetime 更新时间
status tinyint 题目状态,0-正常、1-失效
is_delete tinyint 是否删除,0-正常、1-删除
  • judgeCase:测试用例,包括:
    • input
    • output
  • judge_cases存储json格式的judgeCase对象数组
  • judge_config:判题配置限制,包括:
    • timeLimit:时间限制,单位ms
    • memoryLimit:内存限制,单位KB
    • stackLimit:堆栈限制,单位1

题目提交表

question_submit

列名 数据类型 约束 备注
id bigint primary key id
question_id bigint 题目id
user_id bigint 创建用户 id
user_account varchar(256) 提交用户账号
code text 用户代码
language varchar(128) 编程语言
status tinyint 判题状态,0-待判题、1-判题中、2-成功、3-失败
result varchar(1024) 判题结果,0~5
judge_info text 判题信息(json 对象)
submit_time datetime 提交时间
create_time datetime 创建时间
update_time datetime 更新时间
is_delete tinyint 是否删除,0-正常、1-删除
  • result:判题结果,0-通过、1-答案错误、2-格式错误、3-编译错误、4-运行错误、5-系统错误
  • judge_info:判题详情,包括:
    • time:运行时间
    • memory:占用内存
    • codeLength:代码长度
    • errMessage:判题错误详情,编译错误时为编译错误信息、运行异常时为运行异常信息、答案错误时存储错误答案所用输入用例

建表语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# 数据库初始化
# @author <a href="https://crowntit.github.io">鸦雀</a>

-- 创建库
create database if not exists yoj_v1;

-- 切换库
use yoj_v1;

-- 用户表
create table if not exists user
(
id bigint auto_increment not null comment '用户id' primary key,
user_account varchar(256) unique not null comment '账号',
user_password varchar(512) not null comment '密码',
user_avatar varchar(1024) null comment '用户头像',
user_name varchar(256) null comment '用户昵称',
user_role varchar(256) default 'user' not null comment '用户角色:user/admin',
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint default 0 not null comment '是否删除'
) comment '用户' collate = utf8mb4_unicode_ci;

-- 题目表
create table if not exists question
(
id bigint auto_increment not null comment '题目id' primary key,
title varchar(512) null comment '标题',
content text null comment '内容',
user_id bigint not null comment '创建用户 id',
difficulty tinyint null comment '难度,1-简单、2-中等、3-困难',
tags varchar(1024) null comment '标签列表(json 数组)',
submit_num int default 0 not null comment '题目提交数',
accepted_num int default 0 not null comment '题目通过数',
code_template int default 0 not null comment '代码模板,0-default、>0-核心代码模式的特定模板id',
judge_mode tinyint not null comment '判题模式,1-普通评测、2-特殊评测',
judge_cases text null comment '判题用例(json 对象数组)',
judge_config text null comment '判题配置(json 对象)',
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
status tinyint default 0 not null comment '题目状态,0-正常、1-失效',
is_delete tinyint default 0 not null comment '是否删除'
) comment '题目' collate = utf8mb4_unicode_ci;

-- 题目提交表
create table if not exists question_submit
(
id bigint auto_increment not null comment 'id' primary key,
question_id bigint not null comment '题目 id',
user_id bigint not null comment '提交用户 id',
user_account varchar(256) not null comment '提交用户账号',
code text not null comment '用户代码',
language varchar(128) not null comment '编程语言',
status tinyint default 0 not null comment '判题状态,0-待判题、1-判题中、2-成功、3-失败',
result tinyint default 0 not null comment '判题结果,0-通过、1-答案错误、2-格式错误、3-编译错误、4-运行错误、5-系统错误',
judge_info text null comment '判题信息(json 对象)',
submit_time datetime default CURRENT_TIMESTAMP not null comment '提交时间',
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint default 0 not null comment '是否删除',
index idx_question_id (question_id),
index idx_user_id (user_id)
) comment '题目提交' collate = utf8mb4_unicode_ci;

说明

bigint和long的选择

因为id想要使用ASSIGN_ID的生成算法,所以改成了bigint类型。不选long是因为bigint可容纳的数字大小可以比long更大

使用json字符串存储对象

对于一些需要灵活性的字段,以json字符串的形式存储:

题目表

  • tags:
    • 这里用这种方式存储只是为了方便,只做记录作用
    • 如果需要根据题目标签查询题目、或者严谨处理的话,建议列一个标签的枚举,然后用一个题目_标签表存储关系,字段就是id、question_id、tag_id
  • judge_cases:
    • 因为不同题目的测试用例,数据类型、用例数、单用例参数个数和长度都不同,所以选择这种方式存储
    • 需要严谨处理的话也是需要另开一个用例和题目的关联表,不过那样的话修改数据可能会很麻烦
    • 或许可以处理为某种文件,只存储其uri?不过这个项目初期并不打算做一些文件上传相关的功能
  • judge_config:
    • 包含题目的时间限制timeLimit (单位ms)、内存限制memoryLimit (单位B)、堆栈限制stackLimit
    • 因为不作为查询条件,一般也不频繁更新,字段都属于一类的属性,所以结合在一起存储

题目提交表

  • judge_info:
    • 包含最大执行用时time、最大消耗内存memory、代码长度codeLength和异常信息errMessage。
    • 这里选择用这种方式存储的原因是,memory以B为单位,如果换算为KB会丢失精度、但是以B为单位的话可能结果数字会很大,长度不固定;以及如果判题通过,异常信息可能为空。

分析

  • 以json字符串存储数据比较灵活,json对象的字段可以修改而不影响数据库,json字符串长度也可变
  • 用这种形式存储数据的前提是:所存储的字段不会作为查询条件、数据不需要频繁更新
  • 这种存储方式是违反第一范式的,因为实际上列可再分