首次数据库devise:我是否过度工作?
背景
我是CS的一年级学生,我兼职为爸爸做小生意。 我在现实世界的应用程序开发方面没有任何经验。 我已经在Python中编写脚本,在C中做了一些课程,但没有这样的。
我父亲有一个小型的培训业务,目前所有课程都通过外部networking应用程序进行安排,logging和跟进。 有一个导出/“报告”function,但它是非常通用的,我们需要特定的报告。 我们没有访问实际的数据库来运行查询。 我被要求build立一个自定义的报告系统。
我的想法是创build通用的CSV导出和导入(可能用Python)到每天晚上在办公室托pipe的MySQL数据库中,从那里我可以运行所需的特定查询。 我没有数据库方面的经验,但了解非常基础。 我已经读了一些关于数据库创build和正常forms。
我们可能会很快开始有国际客户,所以我希望数据库在发生这种情况时不会发生爆炸。 我们目前也有一些大公司作为客户,有不同的部门(如ACME母公司,ACME保健部门,ACME人体保健部门)
我提出的模式如下:
- 从客户angular度来看:
- 客户是主桌
- 客户与他们工作的部门有联系
- 部门可以分散在一个国家:伦敦的人力资源部门,斯旺西的市场部门等等。
- 部门与公司的分工有关
- 部门与母公司有联系
- 从课堂angular度看:
- 会议是主桌
- 每个课程都有一位老师
- 每个会话都有一个statusid。 例如0 – 完成,1 – 取消
- 会话被分组为任意大小的“包”
- 每个包都分配给一个客户
- 会议是主桌
我在一张纸上“devise”(更像是潦草的)图案,试图使其保持归一化到第三种forms。 然后我把它插入到MySQL Workbench中,这对我来说非常有用:
( 点击这里查看全尺寸图片 )
替代文字http://maian.org/img/schema.png
示例查询我将会运行
- 哪些还有信用的客户是不活跃的(未来没有上课的客户)
- 每个客户/部门/部门的出席率是多less(由每个会话中的状态ID来衡量)
- 一个月里老师有几堂课
- 举报率低的国旗客户
- HR部门的定制报告,其分部的人员出席率
问题(S)
- 这是过度工程还是我正确的方式?
- 是否需要为大多数查询连接多个表导致性能下降?
- 我已经为客户添加了“lastsession”列,因为这可能是一个常见的查询。 这是一个好主意,还是应该保持数据库严格标准化?
谢谢你的时间
您的问题的更多答案:
1)对于第一次接触这样的问题的人来说,你是非常有目标的。 我认为这个问题上的其他人的指针已经涵盖了很多。 做得好!
2&3)你将会获得的性能将主要取决于具体和优化你的特定查询/程序的正确索引,更重要的是logging的数量。 除非您在主表中谈论了超过一百万条logging,否则您似乎有足够主stream的devise,在合理的硬件上性能不会成为问题。
这就是说,这涉及到你的问题3,在开始的时候,你可能不应该过于担心在这里正常化的正常化的性能或超灵敏度。 这是一个您正在构build的报告服务器,而不是基于事务的应用程序后端,在性能或规范化的重要性方面,这将具有非常不同的configuration文件。 支持实时注册和调度应用程序的数据库必须注意花费几秒钟才能返回数据的查询。 报表服务器function不仅对复杂和冗长的查询有更大的容忍度,而且提高性能的策略也大不相同。
例如,在基于事务的应用程序环境中,您的性能改进选项可能包括将存储过程和表结构重构为第n级,或为less量通常请求的数据开发caching策略。 在报告环境中,您当然可以做到这一点,但是通过引入快照机制,您可以对性能产生更大的影响,在该机制下,计划的进程将运行并存储预configuration的报告,并且您的用户可以在db层上无压力地访问快照数据每个请求的基础上。
所有这些都是一个冗长的咆哮,以说明你所使用的数据库的作用可能与你所使用的devise原则和技巧不同。 我希望这是有帮助的。
你有正确的想法。 你可以清理它,并删除一些映射(有*)表。
你可以在Departments表中添加CityId和DivisionId。
除此之外,我认为一切都很好…
我会做的唯一的变化是:
1-将VARCHAR更改为NVARCHAR,如果您可能要国际化,则可能需要unicode。
2-如果可能的话,改变你的int ID到GUID(uniqueidentifier)(这可能只是我个人的偏好)。 假设您最终达到了拥有多个环境(dev / test / staging / prod)的地步,您可能需要将数据从一个迁移到另一个。 有GUID ID使这变得更容易。
3-为您的公司三层 – >部门 – >部门结构可能不够。 现在,这可能是过度工程,但是你可以概括这个层次结构,以便你可以支持n层深度。 这会使你的一些查询变得更加复杂,因此可能不值得进行折衷。 而且,任何拥有更多图层的客户端都可能很容易“陷入”这种模式。
4-您也在客户端表中有一个状态是一个VARCHAR,并没有链接到状态表。 对于客户状态代表什么,我希望更清楚些。
不,看起来你正在devise一个很好的细节。
我认为国家和公司在你的devise中与城市和部门是同一个实体。 我将摆脱国家和城市表(和Cities_Has_Departments),如有必要,在公司表中添加一个布尔型标志IsPublicSector(或者如果有更多的select不是私人部门/公共部门)。
另外,我认为你的Departments表的用法有错误。 它看起来像部门表格可以作为每个客户部门可以有的各种部门的参考。 如果是这样的话,应该叫做DepartmentTypes。 但是,您的客户(我假设参与者)不属于部门types,他们属于公司中的实际部门实例。 就目前来看,你会知道一个给定的客户属于某个人力资源部门,而不是哪一个!
换句话说,客户端应该连接到您调用Divisions_Has_Departments的表格(但是我只需要调用部门)。 如果是这样,那么如果要在数据库中使用标准参照完整性,则必须如上所述将“城市”折叠为“分区”。
顺便说一下,值得注意的是,如果您已经生成了CSV并想将它们加载到mySQL数据库中,那么LOAD DATA LOCAL INFILE是您最好的朋友: http : //dev.mysql.com/doc/refman/5.1/ en / load-data.html 。 Mysqlimport也值得研究,而且是一个命令行工具,基本上是一个很好的包装加载数据infile。
大部分事情已经说过了,但是我觉得我可以补充一点:年轻的开发人员往往担心performance会有点过头,而且关于join表格的问题似乎正在朝着这个方向发展。 这是一种称为“ 过早优化 ”的软件开发反模式。 试着消除你脑海中的那种reflection:)
还有一件事:你认为你真的需要“城市”和“国家”表吗? 在部门表中没有“城市”和“国家”栏就足够了你的使用情况了? 例如你的申请是否需要按国家城市和城市列出部门?
根据作为商业智能/报告专家和战略/计划经理的angular色发表评论:
-
我同意拉里的方向。 恕我直言,这不是太过于工程,有些事情看起来有点不合适。 为了简单起见,我将客户直接标记为公司ID,部门描述,部门描述,部门typesID,部门typesID。 为了长期的一致性,使用部门typesID和部门typesID作为查找表和内部报告/分析字段的参考。
-
包表中包含“信用”列,不应该实际上绑在客户基础表,所以如果他们很多包,你可以看到多less信用欠留下来的class级? 应用程序可以照顾calc并将其集中存储在Client表中。
-
公司信息可以使用更多的领域,包括明显的地址/电话/等。 信息。 我也准备在D&B“DUNs”专栏(Site / Branch / Ultimate)中添加长期的,Dun&Bradstreet(D&B)有一个巨大的公司目录,你会发现他们的信息很有帮助进行报告/分析。 这将处理您提到的多重分工问题,并允许您为分部/部门/分部/等卷起其层次结构。 大军团。
-
你没有提到你将要使用多less条logging,这可能意味着要设置一个大型的开发计划,而这个计划可以通过预先包装好的“报告”软件来实现更快,更less的麻烦。 如果你不处理大型数据库(<65000)行,确保MS-Access,OpenOffice(Base)或相关的报表/应用程序开发解决scheme无法做到这一点。 我自己使用Oracle的免费APEX软件,它自带的免费数据库Oracle XE只是从他们的网站下载。
-
仅供参考 – 报告洞察:对于大型数据库,通常有两个数据库实例:a)事务数据库,用于logging每个详细logging。 b)安装在另一台机器上的报告数据库(数据集市/数据仓库)。 有关更多信息,请search“星型模式”和“雪花模式”。
问候。
我只想解决一个问题,即join多桌会导致业绩下滑。 不要害怕正常化,因为你必须join。 关系数据库中的联接是正常的和预期的,它们被devise为处理好它们。 您需要设置PK / FK关系(为了保证数据完整性,在devise时考虑这一点非常重要),但在许多数据库中,FK不会自动编入索引。 由于他们将用于连接,你将definitelty要索引的FKS开始。 因为PK必须是唯一的,所以PK通常会得到一个创build索引。 数据仓库的devise确实减less了联接的数量,但通常情况下,只有在数据仓库中有数百万条logging需要在一个报表中访问时,才能达到数据仓库的目的。 即使这样,几乎所有的数据仓库都以事务数据库开始实时收集数据,然后按计划(夜间或每月或任何业务需求)将数据移至仓库。 因此,即使您需要稍后devise数据仓库以提高报告性能,这也是一个好的开始。
我必须说你的devise给一年级的CS学生留下了深刻的印象。
这不是过度devise,这是我如何解决这个问题。 join是好的,不会有太多的性能问题(这是完全必要的,除非你不规范化数据库,这是不推荐!)。 对于状态,请参阅是否可以使用枚举数据types来优化该表。
我曾经在培训/学校领域工作,我想我会指出,你所谓的“会话”(给定课程的实例)和课程本身之间通常存在M:1的关系。 换句话说,你的目录提供的课程(“西class牙语101”或其他),但你可能有一个学期(由史密斯教导,星期三至五日由琼斯教导)的两个不同的实例。
除此之外,这看起来是一个好的开始。 我敢打赌,你会发现客户端领域(通向“客户端”的图表)比你build模的要复杂得多,但是不要太过分了,直到你有了一些真实的数据来引导你。
有几件事想起来了:
-
这些表格似乎适用于报告,但并不真正开展业务。 我想当一个客户报名时,基本上是为客户出席一个会议清单的订单,而这个订单可能是一个公司的多个员工。 看起来“订单”表格真的会成为您系统的核心,从而推动您的数据捕获和最终报告。 (比较您用来运行业务的纸质文档与数据库devise,看看是否存在逻辑匹配。)
-
公司通常没有分裂。 员工有时会更换部门或部门,甚至是中期。 公司有时会添加/删除/重命名部门/部门。 确保表格中可能实时更改的内容不会使后续报告/分组变得困难。 有这么多联系人数据分散在这么多的表中,您可能必须执行非常严格的数据inputvalidation,以保持您的报告有意义和包容性。 例如,当增加一个新客户时,确保他的公司/部门/部门/城市与他的同事具有相同的价值观。
-
“包”的概念并不清楚。
-
既然你指出这是一个小企业,考虑到现有机器的速度和容量,如果性能会成为一个问题,那将是令人惊讶的。
做得好!
不,你不是过度工程,你做得很好。 我记得我的第一个项目,这是一个我已经接受build立的网站,尽pipe我对编程一无所知。 但是,我确实build立了它。 无论如何,在构build第一个数据库devise时,这里有一些有用的技巧
-
保持桌子小(不要浪费空间不必要的)。
-
不要查询比您需要更多的信息。
-
如果您使用ORM,请小心常见的陷阱,例如N + 1问题。
-
远离麻烦的运营商(例如像'%Smith%')。
-
devise你的索引智能化,并确保他们覆盖大部分的用途(这是一个体面的,如果光线,治疗索引)。
-
请记住,基于集合的查询在性能方面通常远远优于遍历数据。
-
知道何时为了性能原因对数据进行非规范化。
-
疼痛什么都可以caching(经济),以减轻数据库。
但是,也有很多工具可以帮助你。 例如,我正在使用我发现最有效的SQLDbm 。
SQLDBM为您提供了一种简单方便的方法,可以在任何浏览器的任何位置绝对地devise您的数据库,而无需任何额外的数据库引擎或数据库build模工具或应用程序。 使用SQLDBM即时devise和pipe理大型和小型数据库和数据模型。 所有这些都包含任何所需的数据库规则和对象,如数据库密钥,模式,索引,列约束和关系。