首次数据库设计:我是否过度工程?

bob*_*nja 245 mysql database schema database-design database-normalization

背景

我是CS的第一年学生,我兼职为我爸爸的小生意做准备.我没有任何实际应用程序开发经验.我用Python编写脚本,用C编写一些课程,但没有这样的.

我父亲有一个小型培训业务,目前所有课程都通过外部网络应用程序进行安排,记录和跟进.有一个导出/"报告"功能,但它非常通用,我们需要特定的报告.我们无权访问实际数据库来运行查询.我被要求建立一个自定义报告系统.

我的想法是创建通用CSV导出并导入(可能使用Python)它们每晚都在办公室中托管的MySQL数据库中,从那里我可以运行所需的特定查询.我没有数据库方面的经验,但了解非常基础知识.我已经阅读了一些关于数据库创建和普通表单的内容.

我们可能很快就会开始拥有国际客户,因此我希望数据库在发生这种情况时不会爆炸.我们目前还有几家大公司作为客户,有不同的部门(例如ACME母公司,ACME医疗保健部门,ACME身体护理部门)

我提出的架构如下:

  1. 从客户的角度来看:
    • 客户是主要的表
    • 客户与他们工作的部门相关联
      • 各部门可以分散在一个国家:伦敦的人力资源部门,斯旺西的市场营销部门等.
      • 部门与公司的部门相关联
    • 部门与母公司相关联
  2. 从班级角度来看:
    • 会话是主要的表格
      • 教师与每个课程相关联
      • 每个会话都有一个statusid.例如0 - 已完成,1 - 已取消
      • 会话被分组为任意大小的"包"
    • 每个包都分配给客户端

我在一张纸上"设计"(更像是潦草书写)模式,试图将其标准化为第三种形式.然后我把电源插头插上到MySQL Workbench和它使人们都非常适合我:
(点击查看全尺寸图片)

替代文字http://maian.org/img/schema.png

示例查询我将运行

  • 哪些有信用额度的客户仍处于闲置状态(未来未安排课程的客户)
  • 每个客户/部门/部门的出勤率是多少(以每个会话中的状态ID来衡量)
  • 一个月有一个老师有几节课
  • 标记出勤率低的客户
  • 人力资源部门的自定义报告,其部门的人员出勤率

问题(S)

  • 这是过度工程还是我正确的方向?
  • 对于大多数查询,是否需要连接多个表会导致性能大幅下降?
  • 我已经向客户添加了"lastsession"列,因为它可能是一个常见的查询.这是一个好主意还是我应该严格规范化数据库?

谢谢你的时间

小智 42

您的问题还有一些答案:

1)对于第一次接近这样的问题的人来说,你几乎已成为目标.我认为到目前为止,其他人对这个问题的指示几乎涵盖了它.做得好!

2&3)您将采取的性能影响很大程度上取决于为您的特定查询/过程拥有和优化正确的索引,更重要的是依赖于记录的数量.除非您在主表中谈论超过一百万条记录,否则您似乎有望采用足够主流的设计,在合理的硬件上性能不会成为问题.

那就是说,这与你的问题3有关,一开始你就不应该过分担心这种正常化的正常化表现或过度敏感.这是您正在构建的报表服务器,而不是基于事务的应用程序后端,它在性能或规范化的重要性方面具有完全不同的配置文件.支持实时注册和调度应用程序的数据库必须注意需要几秒钟才能返回数据的查询.报表服务器功能不仅对复杂和冗长的查询具有更大的容忍度,而且提高性能的策略也大不相同.

例如,在基于事务的应用程序环境中,您的性能改进选项可能包括将存储过程和表结构重构为第n度,或者为少量常用请求的数据开发缓存策略.在报告环境中,您当然可以执行此操作,但通过引入快照机制可以对性能产生更大的影响,其中计划进程运行并存储预配置的报告,并且您的用户访问快照数据而不会对数据库层施加压力每个请求的基础.

所有这些都是一个冗长的咆哮,以说明你所使用的设计原则和技巧可能因你正在创建的数据库的作用而有所不同.我希望这很有帮助.


Rev*_*nzo 14

你有正确的想法.但是,您可以清理它,并删除一些映射(has*)表.

您可以在Departments表中添加CityId和DivisionId.

除此之外,我觉得一切都很好......

  • 如果他想在不同的部门或城市重新使用部门定义,我认为他需要映射表. (4认同)

Jac*_*b G 6

我要做的唯一改变是:
1-将你的VARCHAR改为NVARCHAR,如果你可能会走向国际,你可能想要unicode.

2-如果可能,将您的int id更改为GUID(uniqueidentifier)(这可能只是我个人的偏好).假设您最终到达了多个环境(dev/test/staging/prod),您可能希望将数据从一个环境迁移到另一个环境.让GUID ID变得更加容易.

3-三层为贵公司 - >分部 - >部门结构可能不够.现在,这可能是过度工程,但您可以推广该层次结构,以便您可以支持n级深度.这会使您的一些查询更加复杂,因此可能不值得权衡.此外,可能有任何具有更多层的客户端可能很容易"填充"到该模型中.

4-您还在客户端表中有一个VARCHAR状态,并且没有指向Statuses表的链接.关于客户状态代表什么,我希望更清楚一点.

  • 不同意GUID,不寒而栗.他们的表现可能很糟糕.除非您需要重新说明,否则请勿使用它们. (3认同)

Lar*_*tig 6

不,看起来你的设计水平很高.

我认为国家和公司在您的设计中实际上是同一个实体,城市和部门也是如此.我将摆脱Countries和Cities表(和Cities_Has_Departments),并在必要时将一个布尔标志IsPublicSector添加到Companies表(如果有多个选项而不仅仅是私有部门/公共部门,则添加一个CompanyType列).

另外,我认为您使用Departments表时出错.看起来Departments表可以作为每个客户部门可以拥有的各种部门的参考.如果是这样,它应该被称为DepartmentTypes.但是您的客户(我认为是参加者)不属于部门类型,他们属于公司的实际部门实例.按照现在的情况,你会知道某个客户属于某个人力资源部门,但不是哪一个!

换句话说,客户端应该链接到您调用Divisions_Has_Departments的表(但我只称之为Departments).如果是这样,那么如果要在数据库中使用标准参照完整性,则必须按照上面的讨论将Cities折叠为Divisions.


小智 5

顺便说一下,值得注意的是,如果你已经生成了CSV并希望将它们加载到mySQL数据库中,那么LOAD DATA LOCAL INFILE是你最好的朋友:http://dev.mysql.com/doc/refman/5.1/ en/load-data.html.Mysqlimport也值得研究,它是一个命令行工具,基本上是一个很好的包装加载数据infile.