首页 文章

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

提问于
浏览
238

背景

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

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

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

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

我提出的架构如下:

  • From the client perspective:

  • 客户是主表

  • 客户与他们所工作的部门相关联

  • 部门可以分散在一个国家:伦敦的人力资源部门,斯旺西的市场营销部门等 .

  • 部门与公司的部门相关联

  • 分部与母公司相关联

  • From the classes perspective:

  • 会话是主要表格

  • 教师与每个会话相关联

  • 每个会话都有一个statusid . 例如 . 0 - 已完成,1 - 已取消

  • 会话分组为任意大小的"packs"

  • 每个包都分配给客户端

我"designed"(更像是潦草地写下)一张纸上的图案,试图将其标准化为第三种形式 . 然后我将它插入到MySQL Workbench中,这对我来说非常适合:
Click here for full-sized graphic

alt text http://maian.org/img/schema.png

我将运行的示例查询

  • 哪些仍有信用的客户仍处于闲置状态(未来没有安排课程的客户)

  • 每个客户/部门/部门的出勤率是多少(以每个会话的状态ID衡量)

  • 老师一个月有多少班

  • 标记出勤率低的客户

  • 人力资源部门的自定义报告,其所在部门的人员出勤率

问题

  • Is this overengineered or am I headed the right way?

  • 是否需要为大多数查询加入多个表会导致性能大幅下降?

  • 我已经向客户端添加了一个'lastsession'列,因为它可能是一个常见的查询 . 这是一个好主意还是应该保持数据库严格规范化?

谢谢你的时间

11 回答

  • 1

    顺便说一句,'s worth noting that if you'已经重新生成CSV并希望将它们加载到mySQL数据库中,LOAD DATA LOCAL INFILE是你最好的朋友:http://dev.mysql.com/doc/refman/5.1/en/load-data.html . Mysqlimport也值得研究,它是一个命令行工具,基本上是一个很好的包装加载数据infile .

  • 2

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

    除此之外,它看起来是一个良好的开端 . 我打赌你会发现客户端域(通向“客户端”的图形)比你建模的更复杂,但是在你有一些真实的数据来指导你之前不要过分 .

  • 40

    我要做的唯一改变是:
    1-将VARCHAR更改为NVARCHAR,如果您可能要进入国际市场,则可能需要unicode .

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

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

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

  • 6

    想到了一些事情:

    • 这些表似乎适合报告,但没有真正开展业务 . 我想当客户报名时,主要是为客户出席 Session 列表的订单,该订单可能是针对一家公司的多名员工 . 这似乎是一个“订单”表,它将真正成为您系统的核心,并推动您的数据捕获和最终报告 . (将您用于运行业务的纸质文档与数据库设计进行比较,以查看是否存在逻辑匹配 . )

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

    • “包”概念根本不清楚 .

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

  • 6

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

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

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

  • 3

    它没有过度设计,这就是我如何处理这个问题 . 加入很好,没有太大的性能损失(除非你不推荐将数据库标准化,否则它是完全必要的!) . 对于状态,请查看是否可以使用enum数据类型来优化该表 .

  • 3

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

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

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

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

  • 5

    您的问题还有一些答案:

    1)对于第一次接近这样的问题的人来说,你的目标非常明确 . 我认为迄今为止关于这个问题的其他人的指针几乎涵盖了它 . 做得好!

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

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

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

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

  • 0

    根据作为商业智能/报告专家和战略/计划经理的角色发表评论:

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

    • 包表包含“信用”列,不应该实际上绑定到客户端基表,所以如果他们很多包,你可以看到未来的类留下多少信贷?应用程序可以处理calc并将其集中存储在Client表中 .

    • 公司信息可以使用更多字段,包括明显的地址/电话/等 . 信息 . 我也准备长期添加D&B“DUN”专栏(网站/分支/旗舰版),Dun和Bradstreet(D&B)有一个庞大的公司目录,你会发现他们的信息非常有用用于报告/分析 . 这将处理您提到的多分区问题,并允许您汇总其子/分区/分支/等的层次结构 . 大军团

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

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

    问候 .

  • 14

    我只想解决加入多个表会导致性能损失的问题 . 不要害怕规范化,因为你必须做连接 . 连接在关系数据库中是正常的和预期的,它们旨在很好地处理它们 . 您需要设置PK / FK关系(对于数据完整性,这在设计中需要考虑),但在许多数据库中,FK不会自动编入索引 . 由于它们将在连接中使用,因此您将明确地想要从索引FKS开始 . PK通常会获得创建索引,因为它们必须是唯一的 . 确实,数据仓库设计减少了连接数,但通常只有一个数据仓库需要在一个报表中访问数百万条记录 . 即使这样,几乎所有数据仓库都以事务数据库开始,以实时收集数据,然后按计划(每晚或每月或任何业务需求)将数据移动到仓库 . 因此,即使您需要稍后设计数据仓库以提高报告性能,这也是一个良好的开端 .

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

  • 1

    大多数事情都已经说过了,但我觉得我可以添加一件事:对于年轻的开发人员来说,担心前期的性能有点过分是很常见的,而关于加入表格的问题似乎也是朝这个方向发展的 . 这是一个名为'Premature Optimization'的软件开发反模式 . 试着从脑海中消除那种反射:)

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

相关问题