我编写了这个 SQL 查询并将其用作 hibernate 中的 native 查询。
@Query(
value = "SELECT DISTINCT tp.* FROM TWITTER_POST AS tp " +
"JOIN TWITTER_LIST AS tl " +
"ON tl.owner_id = ?1 " +
"JOIN REL_TWITTER_LIST__ACCOUNTS_TRACKED_BY_LIST AS atbl " +
"ON tl.id = atbl.twitter_list_id " +
"JOIN TWITTER_ACCOUNT AS ta " +
"ON ta.id = atbl.accounts_tracked_by_list_id " +
"LEFT OUTER JOIN REL_TWITTER_POST__TWITTER_USERS_HIDING_POST uhp " +
"ON tp.id = uhp.twitter_post_id " +
"AND uhp.TWITTER_USERS_HIDING_POST_ID = ?1 " +
"WHERE uhp.twitter_post_id is NULL AND ta.id = tp.author_id",
countQuery = "SELECT DISTINCT count(tp.*) FROM TWITTER_POST AS tp " +
"JOIN TWITTER_LIST AS tl " +
"ON tl.owner_id = ?1 " +
"JOIN REL_TWITTER_LIST__ACCOUNTS_TRACKED_BY_LIST AS atbl " +
"ON tl.id = atbl.twitter_list_id " +
"JOIN TWITTER_ACCOUNT AS ta " +
"ON ta.id = atbl.accounts_tracked_by_list_id " +
"LEFT OUTER JOIN REL_TWITTER_POST__TWITTER_USERS_HIDING_POST uhp " +
"ON tp.id = uhp.twitter_post_id " +
"AND uhp.TWITTER_USERS_HIDING_POST_ID = ?1 " +
"WHERE uhp.twitter_post_id is NULL AND ta.id = tp.author_id",
nativeQuery = true
)
Page<TwitterPost> findAllNonHiddenForListsFromTwitterAccountId(Long twitterAccountId, Pageable pageable);
我注意到,与 SQL 工具相比,通过 Hibernate 运行查询时,查询执行速度非常慢。我认为这是因为我使用的是 native 查询而不是 JQPL,JQPL(根据我的阅读)立即进行缓存和分页,而不需要“计数”的定义。尝试将其转换为 JQPL 失败,因为我找不到关于跨联接表的 JQPL 更复杂查询的好教程。
@Query(
value = "SELECT DISTINCT twitterPost " +
"FROM TwitterPost twitterPost " +
"JOIN TwitterList twitterList " +
"ON twitterList.owner.id = ?1 " +
"JOIN TwitterAccount tweetAuthorFromList " +
"ON tweetAuthorFromList IN twitterList.accountsTrackedByLists " +
"WHERE twitterPost.author = tweetAuthorFromList " +
"AND twitterList.owner NOT IN twitterPost.twitterUsersHidingPosts"
)
Page<TwitterPost> findAllNonHiddenPostsFromListsForTwitterAccountId(Long twitterAccountId, Pageable pageable);
显然我的语法已关闭
org.hibernate.exception.SQLGrammarException: could not prepare statement
但是编译器只向我显示生成的 SQL 的问题,而不是 JQPL,所以我一无所知。
还检查了典型的不良性能罪魁祸首,即急切地获取我在各处设置为惰性的实体。
非常感谢有关我的性能问题假设是否正确或转换查询的任何帮助 - 提前致谢!
最佳答案
这里有很多错误:
- 将 SELECT DISTINCT 与 JOIN 结合使用表明您应该改用半连接。
ON tl.owner_id = ?1
用于过滤,而不是用于投影,因此您最好执行 EXISTS 查询。- 假设查询运行缓慢的原因,而不是对其进行分析。之所以在DB工具中运行得更快,是因为DB工具通常会截断结果集,而Spring Data会消耗整个结果集。或者,如果您运行
EXPLAIN
,输出可能来自优化器,甚至无需运行查询。
因此,您可以执行以下操作:
- 使用半连接而不是连接进行过滤。
- 使用
Blaze Persistence
动态编写更好的实体查询。 - 在 JDBC 驱动程序级别配置语句缓存。
- 当查询慢于N秒时,使用慢查询日志记录执行计划。
关于java - Hibernate Native Query 性能不佳且难以转换为 JQPL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69918223/