带有 n:n 个帮助表的数据库表 - 读取两次或重复行?



这是一个关于数据库访问性能与代码简单性和害虫做法的问题。

假设我有一个Users表和一个Addresses表。每个用户可以有多个地址,这些地址将存储在Addresses表中,其中包含Users表的外键。

假设我总是想与用户一起获取地址,从数据库中读取用户的最佳方法是什么?

第一种选择是查询用户,比如通过他的用户名,一旦我有了对象,就使用用户的 id 在Addresses表中查询所有用户的地址。

优点:

  1. 简单代码
  2. 不传输重复数据

缺点:

  1. 需要对数据库进行两次查询

第二种选择是编写一个查询,该查询将UsersAddresses联接,并为用户拥有的每个地址返回用户结果行。除address列外,所有列对于每一行都完全相同。然后,我将所有行聚合到一个带有地址列表的user对象中。

优点:

  1. 需要对数据库进行单个查询

缺点

  1. 相对复杂的代码(聚合用户)
  2. 传输的大量数据是多余的

这是我能想到的两种方式,都有其优点和缺点。您会建议哪个选项?

也许完全是另一种解决方案?

我的第一条经验法则是让数据库引擎做它擅长的事情。表的连接是数据库以最高效率执行的基本功能。数据库的加入将始终比通过进行多个调用可以执行的操作更快。

只有当您在数据传输方面遇到实际问题或数据非常庞大时,您提出的关于它获取大量用户数据这一事实的观点才是正确的。 作为交换,您只对数据库进行一次调用,而不是多次调用。这种节省可以远远超过数据大小的可能缺点。

我不太确定您所说的"聚合用户数据"是什么意思,因为您只是从该用户的第一个条目中获取它并跳过其余条目。

归根结底,让数据库完成它的工作,除非有很好的理由不这样做。

在非常严重的情况下,有一些方法可以在用户数据中引入除第一行之外的所有空值。但是,这使SQL查询变得非常复杂,并且通常不值得开销。

我刚刚在GitHub上与Microsoft进行了长时间的辩论,并与MS-SQL MVP进行了讨论。

总结该线程(来自我的规范):

对于 SQL Server,
  1. 无论是单个查询还是 10 个查询都无关紧要,返回的冗余字段对 SQL Server 的影响为 0。
  2. 无论如何,拆分查询是SQL在内部所做的,当人们尝试优化SQL时,通常是最糟糕的,因为SQL在不强制它以特定方式运行时做得更好。
  3. 具有多个查询会对 SQL 产生开销。
  4. 实际拆分查询唯一解决的是网络上的带宽,因为通过网络传输的字节会更少,他说与有多个查询相比,这可以忽略不计。
  5. 当您有大量返回的行时,由于表假脱机和带宽的原因,您需要拆分查询。

最后,我决定使用

GROUP_CONCAT(DISTINCT addresses.address SEPARATOR ' | ') addresses
...
GROUP BY userId

然后,我将地址拆分为客户端中的列表(特别是在我的客户BeanPropertyRowMapper中)

最新更新