java - Hibernate Native Query 性能不佳且难以转换为 JQPL

标签 java spring-boot hibernate spring-data-jpa

我编写了这个 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,输出可能来自优化器,甚至无需运行查询。

因此,您可以执行以下操作:

  1. 使用半连接而不是连接进行过滤。
  2. 使用 Blaze Persistence 动态编写更好的实体查询。
  3. 在 JDBC 驱动程序级别配置语句缓存。
  4. 当查询慢于N秒时,使用慢查询日志记录执行计划。

关于java - Hibernate Native Query 性能不佳且难以转换为 JQPL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69918223/

相关文章:

java - 如何配置 Spring Boot 以使用两个数据库?

java - 在 Eclipse 中对齐多行 Java 字符串

java - 从实例获取字段?

java - JPA:为什么每个具体类实现表是可选的?

java - 使用 Spring Boot 记录回 TimeBasedRollingPolicy

Spring Data JPA .save() 方法未保存在数据库中

java - 我如何使用 thymeleaf 以一种形式显示 2 个实体的值

java - 从独立的 Java 客户端以编程方式创建 WebLogic 用户

java - 给定数百万个点,找到位于直线上或距直线 0.2 mm 范围内的点

java - Jackson 在构造函数中使用 @JsonProperty 名称进行序列化