将 Doctrine 2 用于大数据模型

Ste*_*eve 2 database model doctrine-orm

我有一个遗留的内部人力资源网络应用程序,我想使用更现代的技术重建它。学说 2 看起来不错。但是我一直找不到关于如何最好地组织大型数据库(120 个表)的实体的文章或文档。你能帮我吗?

我的主要问题是 Person 表(当然!这是一个 HR 系统!)。它目前有 70 列。我想重构它以将几个子集提取到一对一的子表中,这将给我留下大约 30 列。还有大约 50 个其他支持一对多的表,称为 person_address、person_medical、person_status、person_travel、person_education、person_profession 等。稍后会添加更多。

如果我将所有的学说关联(http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html)与 set/ 一起放在 Person 实体类中每个的 get/add/remove 方法,连同原始的 30 列及其方法,以及一些支持的实用程序函数,那么 Person 实体将有 1000 多行长,并且是一场噩梦来测试。

FWIW 我计划创建一个 PersonRepository 来处理常见的批量查询,一个 PersonProfessionRepository 用于该子表上的批量查询/报告等,以及 Person*Service s,它将在需要时包含一些更复杂的业务逻辑。所以组织应用程序逻辑的其余部分很好:这是一个关于如何正确组织大量带有 Doctrine 的子表实体的问题,这些实体都与一个主表有关系/关联。如何避免使 Person 实体类膨胀?

Jas*_*wer 5

识别对象类型

听起来你有一个很好的标准化数据库,我建议你保持这种方式。从people表中删除列以创建一对一关系的单独表对性能和可维护性没有帮助。

您在 Person 实体中识别出几组属性这一事实可能表明您已经找到了Value Object 的案例。甚至一些一对多表(如person_address)听起来更像是Value Object 而不是Entities

从 Doctrine 2.5(在撰写本文时还不稳定)开始,它将支持嵌入单个值对象。不幸的是,我们将不得不等待未来版本来支持Value 对象的集合

撇开这一点,您可以模仿嵌入值对象,Ross Tuck 已在博客中介绍了这一点

千层面代码

您为 Person、PersonProfession 等实施实体、存储库、服务(可能还有控制器?)的计划听起来像是通往Lasagna Code的道路。

如果对您的域没有广泛的了解,我会说您想要一个聚合 Person,其中 Person 实体是聚合根。该聚合需要一个存储库。(但也许我离开这里并且过于简单化,正如我所说,我不知道您的领域。)

为 Person(和其他实体/值对象)创建服务表明数据思维。对于服务,最好考虑行为。考虑您要执行的任务类型,并将连贯的任务集分组到服务中。我怀疑对于 HR 系统,您最终会得到许多围绕 Person 聚合发展的服务。

教义 2 是否合适?

我会说:是的。Doctrine 本身对于大量的表和大量的列没有问题。但是性能在很大程度上取决于您如何使用它。

OLTP 与 OLAP

对于OLTP系统,ORM 非常有用。OLTP 涉及许多短事务,将单个(或列表)聚合写入数据库。

对于OLAP系统,ORM 不适合。OLAP 涉及许多复杂的分析查询,通常会产生大型对象图。对于这类操作,原生 SQL 更加方便。

即使在 OLAP 系统的情况下,Doctrine 2 也可以提供帮助:

  • 您可以使用 DQL 查询(而不是本机 SQL)来利用映射元数据的强大功能。然后使用scalararrayhydration 来获取数据。
  • Doctrine 还支持任意连接,这意味着您可以通过映射元数据连接彼此不关联的实体。
  • 您可以使用 NativeQuery 对象,通过它您可以将结果映射到您想要的任何内容。

我认为 HR 系统是您同时拥有 OLTP 和 OLAP 的完美示例。例如,在向系统添加新人员时使用 OLTP。OLAP 涉及各种报告和分析。

因此,将 ORM 用于事务性操作,而将纯 SQL 用于分析操作并没有错。

做出明智的选择

我认为关键是根据具体情况仔细选择何时使用什么。

Hydrating 实体非常适合事务性操作。利用延迟加载关联可以防止获取您不打算使用的数据。但也可以选择在有意义的地方预先加载某些关联(使用 DQL)。

在处理大型数据集时使用scalararray水合。数据集通常会在您进行分析操作的地方增长,而您实际上并不需要完整的实体。

@Quicker 通过说您可以创建专门的 View 对象来提出一个有效的观点。您可以仅获取特定情况下所需的数据,并手动将该数据塑造成对象。这伴随着他的观点,即不要使用具有特定角色的用户不需要的选项来膨胀用户界面。

您可能想要研究的一种技术是命令查询职责分离(CQRS)。