关于mysql:第一次数据库设计:我是否过度工程?

First-time database design: am I overengineering?

背景

我是CS的一年级学生,我为我爸爸的小企业做兼职。我在实际应用程序开发方面没有任何经验。我已经用python编写了脚本,一些C语言的课程,但没有像这样的。

我爸爸有一个小型的培训公司,目前所有的课程都是通过一个外部网络应用程序来安排、记录和跟进的。有一个export/"reports"功能,但它非常通用,我们需要特定的报告。我们无法访问实际的数据库来运行查询。我被要求建立一个定制的报告系统。

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

我们可能很快就会有国际客户,所以我希望数据库在这种情况下不会爆炸。我们目前也有几个大公司作为客户,拥有不同的部门(例如,Acme母公司、Acme医疗保健部门、Acme保镖部门)

我提出的方案如下:

  • 从客户的角度来看:
    • 客户是主表
    • 客户与他们工作的部门有联系
      • 部门可以分散在一个国家:伦敦的人力资源部、斯旺西的市场营销部等。
      • 部门与公司的部门联系在一起。
    • 分部与母公司关联
  • 从类的角度来看:
    • 会话是主表
      • 教师与每节课都有联系。
      • 为每个会话提供一个statusID。例如0-完成,1-取消
      • 会话被分组成任意大小的"包"
    • 每个包都分配给一个客户端
  • 我"设计"(更像是涂鸦)了一张纸上的模式,试图使它正常化为第三种形式。然后我把它插入到MySQLWorkbench中,它让我觉得很漂亮:(点击这里查看全尺寸的图形)

    alt文本http://maian.org/img/schema.png

    我将运行的查询示例

    • 哪些有信用的客户仍然不活跃(那些没有在将来安排课程的客户)
    • 每个客户/部门/部门的出勤率是多少(以每个会话中的状态ID衡量)
    • 一个老师一个月有几节课
    • 标记出勤率低的客户
    • 为人力资源部门定制报告,包括部门人员的出勤率

    问题(s)

    • 这是过度设计还是我朝着正确的方向走?
    • 对于大多数查询,是否需要连接多个表会导致很大的性能损失?
    • 我向客户机添加了一个"lastsession"列,因为它可能是一个公共查询。这是一个好主意,还是应该严格规范数据库?

    谢谢你抽出时间


    关于您的问题的更多答案:

    1)对于第一次遇到这样的问题的人来说,你是相当有把握的。我认为到目前为止,其他人对这个问题的意见几乎涵盖了这个问题。干得好!

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

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

    例如,在基于事务的应用程序环境中,性能改进选项可能包括将存储过程和表结构重构到第n个级别,或者为少量常见请求的数据开发缓存策略。在报告环境中,您当然可以这样做,但是您可以通过引入快照机制来对性能产生更大的影响,在这种机制中,计划的进程运行并存储预先配置的报告,并且您的用户可以在每个请求的基础上访问快照数据,而不会对您的数据库层造成任何压力。

    所有这些都是长篇大论,用来说明您所使用的设计原则和技巧可能因您所创建的数据库的角色而有所不同。我希望这有帮助。


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

    您可以在"部门"表中添加cityid和divisionid。

    除此之外,我认为一切都很好…


    不,看起来你的设计很细致。

    我认为国家和公司在你的设计中是同一个实体,城市和部门也是。我会去掉国家和城市表(城市有部门),如果必要,在公司表中添加一个布尔标志isPublicSector(如果有比简单的私营部门/公共部门更多的选择,则添加一个companyType列)。

    另外,我认为您在使用部门表时出错。看起来Departments表是对每个客户部门可以拥有的各种部门的引用。如果是这样,它应该称为DepartmentTypes。但是您的客户(我想是与会者)不属于部门类型,而是属于公司中的实际部门实例。现在看来,你会知道某个客户属于某个人力资源部门,而不是哪个部门!

    换句话说,客户应该链接到你所称的部门有部门的表(但我只称为部门)。如果是这样,那么如果您想在数据库中使用标准的引用完整性,那么您必须将城市分解成前面讨论过的分区。


    我唯一要做的改变是:1-将varchar更改为nvarchar,如果您要国际化,可能需要Unicode。

    2-如果可能,将您的int id更改为guid(uniqueidentifier)(这可能只是我的个人偏好)。假设您最终达到拥有多个环境(dev/test/staging/prod)的程度,您可能希望将数据从一个环境迁移到另一个环境。拥有guid id会使这变得非常容易。

    3-贵公司的三层->部门->部门结构可能不够。现在,这可能超出了工程设计的范畴,但是您可以将层次结构归纳为支持n层深度的层次结构。这将使您的一些查询更加复杂,因此可能不值得进行权衡。此外,任何具有更多层的客户机都可能很容易"填充"到此模型中。

    4-客户机表中的状态也是varchar,并且没有到状态表的链接。我希望在这里能更清楚地了解客户状态代表什么。


    顺便说一句,值得注意的是,如果您已经生成了CSV并希望将它们加载到MySQL数据库中,那么加载数据本地中缀是您最好的朋友:http://dev.mysql.com/doc/refman/5.1/en/load-data.html。mysqlimport也是值得一看的,它是一个命令行工具,基本上是一个很好的包装器,用于装载数据。


    根据作为商业智能/报告专家和战略/规划经理的角色,提出以下意见:

  • 我同意上面拉里的指示。嗯,这并不是设计过度,有些东西看起来有点不合适。为了简单起见,我将直接将客户机标记为公司ID、部门描述、部门描述、部门类型ID、部门类型ID。使用部门类型ID和部门类型ID作为查阅表和内部报告/分析字段的参考,以实现长期一致性。

  • packs表包含"credit"列,它不应该实际绑定到客户机基表吗?这样,如果它们有多个packs,您就可以看到为将来的类保留了多少credit?应用程序可以处理calc并将其集中存储在客户机表中。

  • 公司信息可以使用更多的字段,包括明显的地址/电话等信息。我还准备添加D&B"Duns"栏(站点/分支机构/最终),长期来看,Dun和Bradstreet(D&B)有大量的公司目录,稍后您会发现,他们的信息对报告/分析非常有帮助。这将处理您提到的多个师问题,并允许您为大兵团的子/师/支/等汇总其层次结构。

  • 你没有提到你将要处理多少记录,这可能意味着你要建立一个大型的开发计划,这个计划可以用预先打包的"报告"软件更快、更少的麻烦。如果您不处理大型数据库(<65000)行,请确保MS Access、OpenOffice(Base)或相关的报表/应用程序开发解决方案不能做到这一点。我自己也使用过甲骨文的免费apex软件,它附带了甲骨文的免费数据库xe,只需从他们的网站下载即可。

  • 仅供参考—Reporting Insight:对于大型数据库,通常有两个数据库实例a)用于记录每个详细记录的事务数据库。b)报告数据库(数据集市/数据仓库)安装在单独的机器上。有关更多信息,请搜索谷歌的星型和雪花型。

  • 当做。


    大多数事情都已经说过了,但我觉得我可以补充一点:对于年轻的开发人员来说,提前一点担心性能是很常见的,而且您关于加入表的问题似乎是朝着这个方向发展的。这是一个叫做"过早优化"的软件开发反模式。试着把这种反射从你的头脑中消除:)

    还有一件事:你认为你真的需要"城市"和"国家"的桌子吗?部门表中的"城市"和"国家"列是否足以满足您的用例?例如,您的申请是否需要按城市和国家列出部门?


    我只想解决这样一个问题,即加入多张桌子会导致一场演出受到冲击。不要害怕规范化,因为您必须进行连接。联接在关系数据库中是正常的和期望的,并且它们被设计为能够很好地处理它们。您将需要设置pk/fk关系(对于数据完整性,这在设计中很重要),但在许多数据库中,fk不会自动索引。因为它们将用于联接,所以您肯定希望首先索引FK。pks通常在创建时获取一个索引,因为它们必须是唯一的。的确,数据仓库设计减少了连接的数量,但通常只有在一个报表中需要访问数百万条记录时,才能到达数据仓库的位置。即便如此,几乎所有的数据仓库都是从事务数据库开始实时收集数据,然后按计划(每夜或每月或任何业务需要)将数据移动到仓库中。所以这是一个很好的开始,即使您以后需要设计一个数据仓库来提高报表性能。

    我得说,你的设计对一个初一学生来说是令人印象深刻的。


    我在培训/学校领域工作过,我想我会指出,你所说的"课程"(特定课程的实例)和课程本身之间通常存在一种M:1关系。换句话说,你的目录提供了课程("西班牙语101"或其他),但你可能在一个学期内有两个不同的例子(Tuth由史密斯教授,Wed Fri由琼斯教授)。

    除此之外,这似乎是一个良好的开端。我敢打赌,你会发现客户端域(指向"客户端"的图形)比你所建模的域更复杂,但是在你得到一些真正的数据来指导你之前,不要过分考虑这个问题。


    这不是设计过度,这是我解决问题的方法。加入是很好的,不会对性能造成太大影响(除非您将数据库非正常化,否则这是完全必要的,这是不推荐的!)。有关状态,请查看是否可以使用枚举数据类型来优化该表。


    我想到了一些事情:

  • 这些表格似乎适合于报告,但并不是真正运行业务。我会认为,当一个客户注册时,基本上有一个订单是为参加会议的客户下的,这个订单可能是为一家公司的多个员工下的。它看起来像是一个"订单"表,实际上是您系统的中心,驱动您的数据捕获和最终报告。(将用于运行业务的纸质文档与数据库设计进行比较,以查看是否存在逻辑匹配。)

  • 公司通常没有部门。员工有时会更换部门,甚至是在会议中间。公司有时会添加/删除/重命名部门/部门。确保表中可能的实时更改内容不会使后续报告/分组变得困难。由于有如此多的联系人数据被拆分到如此多的表中,您可能需要强制执行非常严格的数据输入验证,以使您的报告具有意义和包容性。例如,添加新客户时,确保其公司/部门/部门/城市与同事的价值观相同。

  • "打包"的概念一点也不清楚。

  • 由于您指出它是一个小企业,考虑到当前机器的速度和容量,如果性能成为一个问题,那将是令人惊讶的。