249

背景

我是 CS 一年级的学生,我为我父亲的小企业做兼职。我在现实世界的应用程序开发方面没有任何经验。我用 Python 写过脚本,用 C 写过一些课程,但没有这样的东西。

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

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

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

我想出的架构如下:

  1. 从客户的角度来看:
    • 客户是主表
    • 客户与他们工作的部门相关联
      • 部门可以分散在一个国家/地区:伦敦的人力资源部,斯旺西的营销部等。
      • 部门与公司的部门相关联
    • 部门与母公司相关联
  2. 从类的角度来看:
    • 会话是主表
      • 每节课都有一位老师
      • 每个会话都有一个 statusid。例如 0 - 已完成,1 - 已取消
      • 会话被分组为任意大小的“包”
    • 每个包都分配给一个客户

我在一张纸上“设计”(更像是潦草)模式,试图将其规范化为第三种形式。然后我将它插入 MySQL Workbench,它对我来说很漂亮:(
单击此处查看全尺寸图形

替代文字
(来源:maian.org

我将运行的示例查询

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

问题)

  • 这是过度设计还是我走对了路?
  • 大多数查询需要连接多个表会导致性能大幅下降吗?
  • 我已经向客户添加了一个“lastsession”列,因为它可能是一个常见的查询。这是一个好主意还是我应该严格规范数据库?

谢谢你的时间

4

11 回答 11

43

您的问题的更多答案:

1)对于第一次解决此类问题的人来说,您几乎是目标。我认为迄今为止其他人关于这个问题的指示几乎涵盖了它。做得好!

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

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

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

所有这些都是冗长的咆哮,以说明鉴于您正在创建的数据库的角色,您采用的设计原则和技巧可能会有所不同。我希望这会有所帮助。

于 2010-02-23T19:44:49.247 回答
14

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

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

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

于 2010-02-23T18:28:30.870 回答
6

我要做的唯一更改是:
1-将您的 VARCHAR 更改为 NVARCHAR,如果您可能要走向国际,您可能需要 unicode。

2- 如果可能,将您的 int id 更改为 GUID(唯一标识符)(这可能只是我个人的偏好)。假设您最终达到了拥有多个环境(dev/test/staging/prod)的地步,您可能希望将数据从一个迁移到另一个。拥有 GUID Id 使这变得更加容易。

3- 您的公司 -> 部门 -> 部门结构的三层结构可能还不够。现在,这可能是过度工程,但您可以概括该层次结构,以便您可以支持 n 级深度。这将使您的某些查询更加复杂,因此可能不值得进行权衡。此外,任何具有更多层的客户端都可能很容易“填充”到此模型中。

4-您在客户端表中还有一个状态,它是一个 VARCHAR,并且没有到状态表的链接。我希望客户端状态代表什么更清楚一点。

于 2010-02-23T18:45:55.377 回答
6

不。看起来您的设计细节水平很高。

我认为国家和公司在你的设计中实际上是同一个实体,城市和部门也是如此。我会删除国家和城市表(以及 Cities_Has_Departments),并在必要时将布尔标志 IsPublicSector 添加到 Companies 表(如果有更多选择而不是简单的 Private Sector / Public Sector,则添加一个 CompanyType 列)。

另外,我认为您对 Departments 表的使用存在错误。看起来 Departments 表可以作为每个客户部门可以拥有的各种部门的参考。如果是这样,它应该被称为 DepartmentTypes。但是您的客户(我假设他们是与会者)不属于部门类型,它们属于公司中的实际部门实例。就目前而言,您将知道给定客户属于某个地方的人力资源部门,但不知道属于哪个!

换句话说,客户应该链接到您称为 Divisions_Has_Departments 的表(但我将简称为 Departments)。如果是这样,那么如果您想在数据库中使用标准的参照完整性,那么您必须将 Cities 折叠为 Divisions(如上所述)。

于 2010-02-23T20:21:54.460 回答
5

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

于 2010-03-01T19:59:52.040 回答
3

大多数事情已经说了,但我觉得我可以补充一点:对于年轻的开发人员来说,预先担心性能有点过分是很常见的,而你关于加入表的问题似乎也朝着这个方向发展。这是一种称为“过早优化”的软件开发反模式。试着从你的脑海中消除这种反射:)

还有一件事:您认为您真的需要“城市”和“国家”表吗?部门表中的“城市”和“国家”列不足以满足您的用例吗?例如,您的应用程序是否需要按城市和国家/地区列出部门?

于 2010-02-23T20:03:13.127 回答
3

以下评论基于作为商业智能/报告专家和战略/规划经理的角色:

  1. 我同意上述拉里的方向。恕我直言,它并没有过度设计,有些东西看起来有点不合适。为简单起见,我会将客户直接标记为公司 ID、部门描述、部门描述、部门类型 ID、部门类型 ID。使用部门类型 ID 和部门类型 ID 作为查找表和内部报告/分析字段的参考,以实现长期一致性。

  2. Packs 表包含“Credit”列,实际上不应该与 Client 基表相关联,因此如果它们有很多包,您可以看到未来课程还剩下多少学分?应用程序可以处理计算并将其集中存储在客户端表中。

  3. 公司信息可以使用更多字段,包括明显的地址/电话/等。信息。我还准备长期添加 D&B“DUNs”列(站点/分支/终极),Dun and Bradstreet (D&B) 拥有庞大的公司目录,以后您会发现他们的信息非常有用用于报告/分析。这将解决您提到的多部门问题,并允许您为子/部门/分支/等卷起他们的层次结构。的大军团。

  4. 您没有提到您将使用多少记录,这可能意味着您为一项大型开发计划做好了准备,使用预打包的“报告”软件可以更快地完成并且少得多的麻烦。如果您不处理大型数据库 (< 65000) 行,请确保 MS-Access、OpenOffice (Base) 或相关的报表/应用程序开发解决方案无法解决问题。我自己也经常使用 Oracle 的免费 APEX 软件,它带有他们的免费数据库 Oracle XE,只需从他们的网站下载即可。

  5. 仅供参考 - 报告洞察:对于大型数据库,您通常有两个数据库实例 a) 用于记录每个详细记录的事务数据库。b) 位于单独机器上的报告数据库(数据集市/数据仓库)。有关更多信息,请搜索 Google Star Schema 和 Snowflake Schema。

问候。

于 2010-02-23T21:53:29.097 回答
2

我只想解决加入多个表会导致性能下降的问题。不要害怕规范化,因为您将不得不进行连接。连接在关系数据库中是正常的和预期的,它们旨在很好地处理它们。您将需要设置 PK/FK 关系(为了数据完整性,这在设计中很重要),但在许多数据库中,FK 不会自动索引。由于它们将在连接中使用,因此您肯定希望从索引 FKS 开始。PK 通常会在创建时获得索引,因为它们必须是唯一的。确实,数据仓库设计减少了连接的数量,但通常只有在一份报告中需要访问数百万条记录时,才能达到数据仓库的目的。即便如此,几乎所有数据仓库都从事务数据库开始实时收集数据,然后按计划(每晚或每月或任何业务需要)将数据移动到仓库。因此,即使您以后需要设计数据仓库来提高报表性能,这也是一个好的开始。

我必须说你的设计对于一年级的 CS 学生来说令人印象深刻。

于 2010-02-24T16:33:27.737 回答
1

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

于 2010-02-23T18:21:04.710 回答
1

我曾在培训/学校领域工作过,我想我会指出,您所谓的“课程”(给定课程的实例)与课程本身之间通常存在 M:1 关系。换句话说,您的目录提供了该课程(“西班牙语 101”或其他),但在一个学期中您可能有两个不同的实例(Tu-Th 由 Smith 教授,Wed-Fri 由 Jones 教授)。

除此之外,这似乎是一个好的开始。我敢打赌,您会发现客户域(通向“客户”的图)比您建模的更复杂,但在您获得一些真实数据来指导您之前,不要过火。

于 2010-02-23T18:40:24.343 回答
0

想到了几件事:

  1. 这些表格似乎适用于报告,但并没有真正运行业务。我认为,当客户注册时,本质上是为参加一系列会议的客户下订单,而该订单可能是针对一家公司的多名员工。看起来“订单”表将真正位于您系统的中心,并推动您的数据捕获和最终报告。(将您用于开展业务的纸质文档与您的数据库设计进行比较,看看是否存在逻辑匹配。)

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

  3. “包”的概念根本不清楚。

  4. 由于您表示这是一家小型企业,考虑到当前机器的速度和容量,如果性能成为问题,那将是令人惊讶的。

于 2010-06-28T00:02:09.523 回答