Sql 优化查询-使用字段或其他表
我有一个查询需要很长时间,我想优化它。我在寻找最有效的方法 我正在使用Postgresql DB开发Hibernate/JPA,但任何解决方案都应该是通用的JPA解决方案 术语Sql 优化查询-使用字段或其他表,sql,hibernate,database-design,jpa,Sql,Hibernate,Database Design,Jpa,我有一个查询需要很长时间,我想优化它。我在寻找最有效的方法 我正在使用Postgresql DB开发Hibernate/JPA,但任何解决方案都应该是通用的JPA解决方案 术语 用户:系统中的用户 朋友:用户的朋友。一个用户将有N个朋友 会话:使用系统的会话。可以打开或关闭 上下文:会话的上下文。在任何给定的时间内,用户可能在每个上下文中有一个打开的会话,并且可能在每个上下文中有许多过去关闭的会话 查询 我需要实现一个查询,在给定用户名的情况下,该查询将提供以下信息: 获取该用户的所有好友
- 用户:系统中的用户
- 朋友:用户的朋友。一个用户将有N个朋友
- 会话:使用系统的会话。可以打开或关闭李>
- 上下文:会话的上下文。在任何给定的时间内,用户可能在每个上下文中有一个打开的会话,并且可能在每个上下文中有许多过去关闭的会话李>
- 获取该用户的所有好友
- 每一位朋友:
- 如果朋友有任何打开的会话,则获取所有打开的会话(针对所有上下文)
- 否则,请从所有上下文中获取好友的最新会话
- 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:公开会议
- 为“最新会话”创建新实体和表
- 该表将包含以下列:
- 使用者
- 上下文
- 最新会话ID
- 该表将由会话实体在持久化后更新,因此任何新持久化的会话都将自动更新该表
- 新查询将从此表中获取用户所有好友的所有记录,并对其进行处理以创建最终结果李>
- 为最新字段创建新字段(布尔值)
- 该列将由会话实体的post persist设置,这样以前的“最新”会话将不再是最新的会话,而新会话将成为最新的会话
- 新查询将从原始sessions表中获取用户所有好友的所有最新记录(通过将新列合并到语句的条件中),并对其进行处理以创建最终结果李>
每种方法都有利弊,我们似乎还没有赢家。显然,我们还没有考虑到其他更好的解决方案。我想看看上面哪一个更好,为什么更好,或者你自己的一个更好的新方法。为什么不缓存对象?您不需要点击数据库。两种解决方案之间的差异应该是微不足道的。表解决方案可能更干净,具体取决于活动 然而,一定要注意“你做错了”(根据理论) RDBMS应用程序设计原则明确指出,您不应该尝试指定查询的执行方式,而应该指定您需要的数据。数据库将找到解决方案的最佳路径(RDBMS距离数据最近,根据您的体系结构,它可能会节省网络往返、存储往返等等;在这里,可扩展性可能会严重受损,如果您不进行适当的压力测试,您可能不会意识到这一点;此外,RDBMS知道索引和内部统计信息,这些信息决定了扫描或查找是否有效更有效,它知道如何以最佳方式执行连接) 在实践中,试着提出这样一个问题:为什么不同的数据库用于友谊?(是真的不同的数据库还是同一数据库上的不同模式?) 此外,如果您真的想按自己的方式去做(禁用RDBMS以寻找最佳执行计划),那么最重要的因素是:
- 索引(将以数量级影响性能)
- 使用模式(索引将提高选择的性能,但太多的索引将减慢更新速度)
- 应用程序/客户端层缓存(可能会影响性能和可伸缩性,数量级)
SELECT *
FROM Sessions s
WHERE s.End IS NULL
AND s.User IN (:friendsList)
UNION ALL
SELECT *
FROM Sessions s
WHERE s.User NOT IN (SELECT User
FROM Sessions s2
WHERE s2.User IN (:friendsList)
AND s2.End IS NULL)
AND s.User IN (:friendsList)
AND s.End IN (SELECT MAX(End)
FROM Sessions s2
WHERE s2.User = s.User)