【发布时间】:2011-02-28 10:01:38
【问题描述】:
我有一个查询需要很长时间,我想优化它。我正在寻找最有效的方法。
我正在使用 Postgresql DB 开发 Hibernate/JPA,但任何解决方案都应该是通用 JPA 解决方案。
术语
- 用户:系统中的用户。
- 朋友:用户的朋友。一个用户将有 N 个朋友。
- 会话:使用系统的会话。可以打开或关闭。
- 上下文:会话的上下文。用户在任何给定时间每个上下文可能有一个打开的会话,并且每个上下文可能有许多过去关闭的会话。
查询
我需要实现一个查询,给定一个用户名,给我以下信息:
- 获取该用户的所有朋友
- 对于每个朋友:
- 如果朋友有任何打开的会话,则获取所有打开的会话(针对所有上下文)
- 否则,从所有上下文中获取朋友的最新会话。
请注意,友谊存储在不同的数据库中,因此无论如何我都无法将其合并到一个大查询中。
示例
用户 A 有三个朋友:B、C、D。有两种情况,1和2。朋友们有以下数据:
(下面的格式是 Session ID - User,Context)
- 1 - B,1:打开会话
- 2 - B,2:2 月 27 日开始的闭会
- 3 - B,2:2 月 26 日开始的闭门会议
- 4 - C,1:2 月 27 日开始的闭门会议
- 5 - C,1:2 月 26 日开始的闭门会议
- 6 - C,2:2 月 26 日开始的闭门会议
- 7 - C,2:2 月 25 日开始的闭门会议
- 8 - D,1:打开会话
- 9 - D,2:打开会话
查询应该让我知道: B:第 1 课(所有公开课) C: Session 4 (最近的闭幕会议) D: Sessions 8,9(所有开放的会话)
当前状态
我的查询分三个步骤进行:
- 获取用户的所有好友
- 对于每个朋友:
- 获取朋友的所有开放会话
- 如果有任何打开的会话,返回所有打开的会话
- 获取朋友的最新会话,返回该会话
显然这是很多查询。 首先,我将执行上面的第 2 步并将其转换为单个查询。我的担忧与第二个查询有关。问题是 - 如何使其更加优化。因此问题可以重新表述:
“给定一组 N 个好友 ID,获取所有这些好友的所有打开会话或最新会话。”
建议的解决方案
基本上我们想出了两个解决方案,我们正在考虑什么会更好。
表格解决方案表示要保留一个新表格,该表格将在用户、上下文和最新会话之间建立关联。该解决方案的含义是:
- 为“最新会话”创建一个新实体和表
- 该表将包含以下列:
- 用户
- 上下文
- 最新会话 ID
- 该表将在 post persist 时由会话实体更新,因此任何新持久化的会话都将自动更新该表。
- 新查询将从该表中获取用户所有朋友的所有记录,并对其进行处理以创建最终结果。
列解决方案说要在会话表上保留一个“最新”标志列。该解决方案的含义是:
- 为最新的(布尔值)创建一个新字段
- 该列将由会话实体的 post persist 设置,使之前的“最新”会话不再是最新的,新的会话将成为最新的。
- 新查询将从原始会话表中获取用户所有朋友的所有最新记录(通过将新列合并到语句的条件中),并对其进行处理以创建最终结果。
这些各有利弊,我们似乎还没有赢家。显然,我们可能还没有考虑其他更好的解决方案。我想看看上面哪一个更好,为什么,或者你自己的更好的新方法。
【问题讨论】:
-
如何使用带有函数的视图?如果可能的话,缓存也可能有很大帮助。
-
据我了解,视图只会以一种或另一种方式运行复杂的查询,我试图通过在数据库更新期间进行更多管理来避免这种情况,从而改善查询的性能。
-
友谊数据库为什么不同?真的是不同的数据库还是不同的架构?
标签: sql hibernate database-design jpa