【问题标题】:spring mvc hibernate performance issuesspring mvc休眠性能问题
【发布时间】:2011-07-11 05:18:15
【问题描述】:

我们正在开发一个带有 hibernate 的 spring mvc 项目。

当我们执行以下代码时:

try {
    HibernateTemplate ht = new HibernateTemplate(sf);
    List<Route> r = ht.findByNamedParam("select r from Route r inner join r.carPoolers as carPooler where (( r.owner.id  = :userid ) or ( carPooler.user.id = :userid )) AND r.id =:routeID", new String[]{"userid", "routeID"} , new Object[]{ u.getId() , id});
    if (r.size() == 1) {
        return r.get(0);
    } else {
        return null;
    }
} catch (DataAccessException ex) {
    LogFactory.getLog(RouteRepository.class).fatal(ex);
    return null;
}

这是结果:

SELECT ROUTE0_.ID AS ID4_, ROUTE0_.ARRIVALTIME AS ARRIVALT2_4_, 
    ROUTE0_.CAR_ID AS CAR13_4_, ROUTE0_.DATE AS DATE4_, 
    ROUTE0_.DAYOFWEEK AS DAYOFWEEK4_, ROUTE0_.DEPARTURETIME AS 
    DEPARTUR5_4_, ROUTE0_.ENDDATE AS ENDDATE4_, ROUTE0_.MESSAGEID 
    AS MESSAGEID4_, ROUTE0_.OPENSEATS AS OPENSEATS4_, 
    ROUTE0_.OWNER_ID AS OWNER14_4_, ROUTE0_.ROUTECACHE_ID AS 
    ROUTECACHE11_4_, ROUTE0_.ROUTEOPTIMIZED AS ROUTEOPT9_4_, 
    ROUTE0_.START_ID AS START12_4_, ROUTE0_.STOP_ID AS STOP10_4_ 
FROM ROUTE ROUTE0_ INNER JOIN CARPOOLER CARPOOLERS1_ ON 
    ROUTE0_.ID=CARPOOLERS1_.ROUTEID 
WHERE (route0_.owner_id=? or carpoolers1_.user_id=?) and route0_.id=?

    SELECT CAR0_.ID AS ID5_3_, CAR0_.BRAND_ID AS BRAND8_5_3_, CAR0_.CARNAME 
        AS CARNAME5_3_, CAR0_.CARTYPE AS CARTYPE5_3_, CAR0_.IMAGEURL AS 
        IMAGEURL5_3_, CAR0_.PRICEKM AS PRICEKM5_3_, CAR0_.SEATS AS 
        SEATS5_3_, CAR0_.USER_ID AS USER7_5_3_, BRAND1_.ID AS ID6_0_, 
        BRAND1_.BRANDNAME AS BRANDNAME6_0_, USER2_.ID AS ID0_1_, 
        USER2_.EMAIL AS EMAIL0_1_, USER2_.FACEBOOKID AS FACEBOOKID0_1_, 
        USER2_.FIRSTNAME AS FIRSTNAME0_1_, USER2_.GENDER AS GENDER0_1_, 
        USER2_.IMAGEURL AS IMAGEURL0_1_, USER2_.LANGUAGE_ID AS 
        LANGUAGE12_0_1_, USER2_.LASTNAME AS LASTNAME0_1_, 
        USER2_.MOBILEPHONE AS MOBILEPH8_0_1_, USER2_.PASSWORD AS 
        PASSWORD0_1_, USER2_.SMOKER AS SMOKER0_1_, USER2_.TELEPHONE AS 
        TELEPHONE0_1_, LANGUAGE3_.ID AS ID9_2_, LANGUAGE3_.LANGUAGE AS 
        LANGUAGE9_2_, LANGUAGE3_.LANGUAGECODE AS LANGUAGE3_9_2_ 
    FROM CAR CAR0_ LEFT OUTER JOIN BRAND BRAND1_ ON 
        CAR0_.BRAND_ID=BRAND1_.ID LEFT OUTER JOIN USER USER2_ ON 
        CAR0_.USER_ID=USER2_.ID LEFT OUTER JOIN LANGUAGE LANGUAGE3_ ON 
        USER2_.LANGUAGE_ID=LANGUAGE3_.ID 
    WHERE car0_.id=?

    SELECT USER0_.ID AS ID0_1_, USER0_.EMAIL AS EMAIL0_1_, 
        USER0_.FACEBOOKID AS FACEBOOKID0_1_, USER0_.FIRSTNAME AS 
        FIRSTNAME0_1_, USER0_.GENDER AS GENDER0_1_, USER0_.IMAGEURL AS 
        IMAGEURL0_1_, USER0_.LANGUAGE_ID AS LANGUAGE12_0_1_, 
        USER0_.LASTNAME AS LASTNAME0_1_, USER0_.MOBILEPHONE AS 
        MOBILEPH8_0_1_, USER0_.PASSWORD AS PASSWORD0_1_, USER0_.SMOKER 
        AS SMOKER0_1_, USER0_.TELEPHONE AS TELEPHONE0_1_, LANGUAGE1_.ID 
        AS ID9_0_, LANGUAGE1_.LANGUAGE AS LANGUAGE9_0_, 
        LANGUAGE1_.LANGUAGECODE AS LANGUAGE3_9_0_ 
    FROM USER USER0_ LEFT OUTER JOIN LANGUAGE LANGUAGE1_ ON 
        USER0_.LANGUAGE_ID=LANGUAGE1_.ID 
    WHERE user0_.id=?

    SELECT ROUTECACHE0_.ID AS ID7_2_, ROUTECACHE0_.AANTALM AS AANTALM7_2_, 
        ROUTECACHE0_.AANTALMIN AS AANTALMIN7_2_, ROUTECACHE0_.ACTIVE AS 
        ACTIVE7_2_, ROUTECACHE0_.JSON AS JSON7_2_, 
        ROUTECACHE0_.LOCATIONS AS LOCATIONS7_2_, 
        ROUTECACHE0_.LOCATIONSOPTIMIZED AS LOCATION7_7_2_, 
        ROUTECACHE0_.ROUTEOPTIMIZED AS ROUTEOPT8_7_2_, 
        ROUTECACHE0_.START_ID AS START10_7_2_, ROUTECACHE0_.STOP_ID AS 
        STOP9_7_2_, LOCATION1_.ID AS ID2_0_, LOCATION1_.LANG AS 
        LANG2_0_, LOCATION1_.LAT AS LAT2_0_, LOCATION1_.NUMBER AS 
        NUMBER2_0_, LOCATION1_.STREET AS STREET2_0_, LOCATION1_.ZIPCODE 
        AS ZIPCODE2_0_, LOCATION2_.ID AS ID2_1_, LOCATION2_.LANG AS 
        LANG2_1_, LOCATION2_.LAT AS LAT2_1_, LOCATION2_.NUMBER AS 
        NUMBER2_1_, LOCATION2_.STREET AS STREET2_1_, LOCATION2_.ZIPCODE 
        AS ZIPCODE2_1_ 
    FROM ROUTECACHE ROUTECACHE0_ LEFT OUTER JOIN LOCATION LOCATION1_ ON 
        ROUTECACHE0_.START_ID=LOCATION1_.ID LEFT OUTER JOIN LOCATION 
        LOCATION2_ ON ROUTECACHE0_.STOP_ID=LOCATION2_.ID 
    WHERE routecache0_.id=?

     SELECT ROUTECACHE0_.ROUTECACHESPUNTENTUSSEN_ID AS ROUTECAC1_1_, 
        ROUTECACHE0_.ROUTECACHETUSSENPUNTEN_ID AS ROUTECAC2_1_, 
        LOCATION1_.ID AS ID2_0_, LOCATION1_.LANG AS LANG2_0_, 
        LOCATION1_.LAT AS LAT2_0_, LOCATION1_.NUMBER AS NUMBER2_0_, 
        LOCATION1_.STREET AS STREET2_0_, LOCATION1_.ZIPCODE AS 
        ZIPCODE2_0_ 
    FROM ROUTECACHE_LOCATION_PUNTEN ROUTECACHE0_ LEFT OUTER JOIN LOCATION 
        LOCATION1_ ON 
        ROUTECACHE0_.ROUTECACHETUSSENPUNTEN_ID=LOCATION1_.ID 
    WHERE routecache0_.routecachesPuntenTussen_id=?

     SELECT CARPOOLERS0_.ROUTEID AS ROUTEID5_, CARPOOLERS0_.ID AS ID5_, 
        CARPOOLERS0_.ID AS ID3_4_, CARPOOLERS0_.APPROVED AS 
        APPROVED3_4_, CARPOOLERS0_.ONETIME AS ONETIME3_4_, 
        CARPOOLERS0_.ROUTEID AS ROUTEID3_4_, CARPOOLERS0_.START_ID AS 
        START5_3_4_, CARPOOLERS0_.STOP_ID AS STOP7_3_4_, 
        CARPOOLERS0_.USER_ID AS USER6_3_4_, LOCATION1_.ID AS ID2_0_, 
        LOCATION1_.LANG AS LANG2_0_, LOCATION1_.LAT AS LAT2_0_, 
        LOCATION1_.NUMBER AS NUMBER2_0_, LOCATION1_.STREET AS 
        STREET2_0_, LOCATION1_.ZIPCODE AS ZIPCODE2_0_, LOCATION2_.ID AS 
        ID2_1_, LOCATION2_.LANG AS LANG2_1_, LOCATION2_.LAT AS LAT2_1_, 
        LOCATION2_.NUMBER AS NUMBER2_1_, LOCATION2_.STREET AS 
        STREET2_1_, LOCATION2_.ZIPCODE AS ZIPCODE2_1_, USER3_.ID AS 
        ID0_2_, USER3_.EMAIL AS EMAIL0_2_, USER3_.FACEBOOKID AS 
        FACEBOOKID0_2_, USER3_.FIRSTNAME AS FIRSTNAME0_2_, 
        USER3_.GENDER AS GENDER0_2_, USER3_.IMAGEURL AS IMAGEURL0_2_, 
        USER3_.LANGUAGE_ID AS LANGUAGE12_0_2_, USER3_.LASTNAME AS 
        LASTNAME0_2_, USER3_.MOBILEPHONE AS MOBILEPH8_0_2_, 
        USER3_.PASSWORD AS PASSWORD0_2_, USER3_.SMOKER AS SMOKER0_2_, 
        USER3_.TELEPHONE AS TELEPHONE0_2_, LANGUAGE4_.ID AS ID9_3_, 
        LANGUAGE4_.LANGUAGE AS LANGUAGE9_3_, LANGUAGE4_.LANGUAGECODE AS 
        LANGUAGE3_9_3_ 
    FROM CARPOOLER CARPOOLERS0_ LEFT OUTER JOIN LOCATION LOCATION1_ ON 
        CARPOOLERS0_.START_ID=LOCATION1_.ID LEFT OUTER JOIN LOCATION 
        LOCATION2_ ON CARPOOLERS0_.STOP_ID=LOCATION2_.ID LEFT OUTER 
        JOIN USER USER3_ ON CARPOOLERS0_.USER_ID=USER3_.ID LEFT OUTER 
        JOIN LANGUAGE LANGUAGE4_ ON USER3_.LANGUAGE_ID=LANGUAGE4_.ID 
    WHERE carpoolers0_.RouteId=?

问题:

  • 这至少需要 460 毫秒。
  • 我们只需要第一次查询我们的结果。

, 提前联系

【问题讨论】:

    标签: sql hibernate spring-mvc


    【解决方案1】:

    您可能有很多查询,因为某些关系是预先加载的。请注意,默认情况下,所有 OneToOne 和 ManyToOne 关系都是预先加载的。这意味着如果一条路线有汽车、有用户、有语言等,Hibernate 每次加载一条路线时都会加载所有这些引用的实体。

    改为让它们延迟加载,并调整您的查询以仅获取您需要的实体。

    【讨论】:

    • 我们尝试延迟加载所有内容,这会导致更多查询和相同的响应时间:)。谢谢
    • hibernate 是否使用 hql 查询中的惰性设置?
    • 是的,确实如此。如果它仍然加载所有内容,则意味着您有一些遍历关系的代码(可能是一个 toString 调用,它会递归调用拥有的实体的 toString)
    • 它在存储库本身中执行此操作。从列表初始化的那一刻起,他就完成了所有这些查询。之后的代码中没有。
    【解决方案2】:

    我猜返回的对象被传递给一些自动序列化器(你使用@ResponseBody,是吗?),它试图序列化整个可访问对象的图形,因此会触发你不需要的相关对象的延迟加载。

    如果是这样,您可以创建一个仅包含必要字段的DTO,从加载的实体填充它并返回该 DTO 而不是实体。

    另一种方法是配置序列化程序以使其仅序列化必要的字段,但它可能更复杂。

    【讨论】:

    • 我们不使用@ResponseBody。在我们得到这些查询的那一刻,没有任何序列化的东西。 :)
    • @izar: 你如何使用r.get(0);的结果?
    【解决方案3】:

    请参阅此处了解如何仅获得 1 个结果:How do you do a limit query in HQL?

    您是否在表上配置了索引?

    【讨论】:

    • 是的,我们已经为我们的表格建立了索引 :)
    猜你喜欢
    • 2015-11-19
    • 2016-12-06
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    • 2017-01-02
    • 2012-03-23
    • 2012-01-02
    • 1970-01-01
    相关资源
    最近更新 更多