kul*_*eep 10 mysql database database-design
我正在开发一个多选在线测试项目,我已经设计了数据库来存储结果,但寻找更优化的方法.
要求:
我的设计:
表:
学生
stud_id,姓名,电子邮件
测试
test_id,testname,duration
问题
que_id,问题,opt1,opt2,opt3,opt4,answer,test_id
回答
stud_id,que_id,回答
通过这种方式可以存储答案但是它增加了记录的数量,因为学生新记录解决的每个问题都将被添加到答案表中.
例如,一个测试包含100个问题,1000个学生参加该测试,每个学生每个问题将有100个记录,1000个学生将有100个记录.
有没有更好的方法来做到这一点,记录数量会减少.
Per*_*DBA 16
你做得很好.就数据而言,设计是正确的,但不完整.有两个错误:
opt1…opt4
是一个重复的群体,打破2NF.它必须放在一个单独的表中.
此外,似乎没有选项名称或描述符,这很奇怪(您在页面上绘制什么,在每个单选按钮旁边?)
如果您添加了第五个选项,那么现在可以满足; 如果你有少于四个选项的问题,现在可以满足.
相反,您有一组固定的列,如果将来有任何此类更改,您必须更改数据库和现有代码.并且代码将是可怕的(额外处理而不是直接SELECT)
你的answers
桌子没有完整性.就目前而言,答案可以根据学生未被问到的问题或者学生没有参加的考试来记录.防止这种类型的错误是关系数据库中的普通费用,并且在记录归档系统中是不可能的.
在IT的这些黑暗时期,这是一个普遍的趋势.人们关注数据价值 ; 他们想象电子表格中的值,它们直接用于实现包含这些值的对象.而不是理解数据及其含义.
answers(stud_id, que_id, answer)
没有任何意义,没有完整性,除非断言student_test的上下文.
第三项不是错误,因为您没有将其作为要求.但是,在我看来,一个问题可以在多个测试中使用.你设置它的方式,这些问题将被复制(数据库的重点是规范化它,这样就没有重复).
test_question.
通过这种方式可以存储答案但是它增加了记录的数量,因为学生新记录解决的每个问题都将被添加到答案表中.
是.这对数据库来说是正常的.
有没有更好的方法来做到这一点,记录数量会减少.
对于记录文件系统,是的.对于数据库,没有.既然你已经将你的问题标记为数据库设计,我会认为这就是你想要的.
数据库是事实的集合,而不是具有相关字段的记录.事实是关于现实世界,仅限于数据库和应用程序的范围.
确定我们需要的离散事实很重要,因为从属事实依赖于高阶事实.那就是数据库设计.而且,随着我们的进步,我们将数据规范化,作为同一个练习的一部分.规范化的目的是消除重复,否则您有更新异常.当我们进步时,我们再次确定关系密钥,作为同一个练习的一部分.关系密钥提供关系数据库的逻辑结构,即.逻辑完整性.
例如,一个测试包含100个问题,1000个学生参加该测试,每个学生每个问题将有100个记录,1000个学生将有100个记录.
是.但这在ISAM记录处理术语中表达.在数据库术语中,您无法绕过数据库存储的事实:
关于100个问题的事实
约1000名学生的事实
大约1,000名学生的事实乘以他们做出的100项选择
你需要了解两件事:大量不连续的事实; 和复合键的使用.两者都对关系数据库至关重要.如果其中任何一个丢失,或者你不情愿地实现它们,你就不会拥有关系数据库的完整性,功能或速度,你将拥有1970年以前的ISAM记录文件系统.
此外,SQL平台,以及某种程度上的NONsql平台,如myNONsql,都经过大量优化,可以处理数据集(不是逐个记录); 繁重的I/O和缓存; 如果实现高并发性所需的结构,您将获得更高的性能.
就实现而言,特别是因为您关注性能,所以存在错误.重述是,在理解和建模数据之前不应尝试实施.
全面的问题是,你已经添加了一个代理(没有"代理密钥"这样的东西,它只是一个代理,一个物理记录ID).在模拟练习中还有很长的路要走; 它进展不够; 模型不稳定,添加代理人.
代理总是一个额外的列加上基础索引.显然,这会消耗资源,并且在插入和删除方面会产生成本.
代理不提供行唯一性,这是关系数据库中所要求的.
在关系模型要求是将密钥从数据组成.关系键提供行唯一性.
代理人不是由数据组成的.因此,它不是关系密钥,并且它不提供任何一个的质量.
如果使用代理,它不会替换密钥,它是密钥的补充.这就是为什么我们在数据建模之后而不是之前评估代理的需求.这是一个实现问题,而不是建模问题.
让我提供提案,而不是来回走动,你可以讨论它.
学生测试数据模型(仅限第1页,用于进展后的那些).
如果您不习惯乐谱,请注意每个小刻度,刻痕和标记,实线与虚线,方形与圆角,意味着非常具体的东西.请参阅IDEF1X表示法.
对于test
和question.
我已经离开id
在列,但请注意,您将与短的,有意义的代码好得多.
student_id
是有效的,因为这两个name
和email
太大迁移到子表.
请仔细检查动词短语,它们包含一组谓词.其余的Predicates可以直接从模型中确定.如果不清楚,请询问.
看看你是否可以确定这是一个事实的集合,每个事实都是离散的,因为其他事实依赖于它; 它不是具有相关字段的记录集合.
你的
answers
桌子没有完整性.就目前而言,答案可以根据学生未被问到的问题或者学生没有参加的考试来记录.防止这种类型的错误是关系数据库中的普通费用,并且在记录归档系统中是不可能的.
answers
现在命名的表格student_response,
具有一定的完整性.A student
被注册为测试,student_test,
并student_responses
受到约束student_test.
请评论/讨论.
我将添加额外的表主题(subject_id,subject_name)并在问题表中添加该subject_id,因为FK可以吗?
是的,无论如何.但这会产生后果.一些建议,以确保我们全面正确地做到这一点:
如上所述,除非绝对必要,否则不要使用代理(记录ID).对于用户和开发人员而言,短代码对于标识符来说要好得多.
ID
列的相关问题的更多信息,请阅读本答案.主题很重要.它是(a)question
存在,(b)test
存在的背景.它们确实作为独立项目存在(DM的第1页),但现在它们从属于subject.
附加项目.这种添加大大提高了数据的完整性.
学生注册的事实和学生参加考试的事实是离散的和单独的事实.
感激不尽,消除了两个代理人question_id
和test_id.
短消息codes
等CHAR(2)
更容易,也更有意义.
注意表名的改进,提高了清晰度.
我更新了学生测试数据模型(仅限第2页,用于进展后的那些).
然而,这暴露了一些东西(这就是为什么我们建模数据,纸张便宜,许多草稿是正常的).如果我们评估Predicates(在数据模型中很容易看到,详见IDEF1X Notation文档):
each subject_test was taken by 0-to-n student_tests
each student_test is [a taking of] 1 subject_test
each student took 0-to-n student_tests
each student_test is taken by 1 student
Run Code Online (Sandbox Code Playgroud)
那些谓词不准确.一个student
可以坐test
任何subject.
给定的新subject
表,我认为我们要students
进行注册subjects,
,因此student_test
要受到约束subjects
的student
注册了.
我更新了学生测试数据模型(第3页).现在,我们有更多的完整性,从而student_test
对被限制subjects
的student
注册了.相关的谓词是:
each student registered for 0-to-n student_subjects
each student_subject is a registration of 1 student
each subject attracted 0-to-n student_subjects
each student_subject is an attraction of 1 subject
each subject_test was taken by 0-to-n student_tests
each student_test is [a taking of] 1 subject_test
each student_subject took 0-to-n student_tests
each student_test is taken by 1 student_subjects
Run Code Online (Sandbox Code Playgroud)现在数据模型似乎已完成.
Context是数据库中的所有内容.
数据层次结构在密钥的复合中清晰可见.
请注意,子表中的关系键为层次结构中的每个更高级别(父级,祖父级)提供与父表的关系完整性.
如果不明显,请注意Relational Joins的强大功能.对于ID
在每个文件中都有字段的记录归档系统,您无法做到的事情.例如:
加入student_response
直接subject
上subject_code
,而无需导航两个水平之间
加入student_response
直接student
上student_id
,而无需导航两个水平之间
不,没有更好的设计,因为设计与表中的记录数无关.无论你是处理十个学生还是一万个学生,你都会选择相同的设计.
你的桌子设计看起来不错.不要担心记录的数量.dbms用于处理大型表.而100k记录仍然是一个小型数据库.如果存在数十亿的答案,我甚至不会改变这种设计.
归档时间: |
|
查看次数: |
7762 次 |
最近记录: |