【问题标题】:Is my Java Hibernate application using Prepared Statement Pooling?我的 Java Hibernate 应用程序是否使用准备好的语句池?
【发布时间】:2019-02-09 21:06:42
【问题描述】:

我正在使用 Hibernate 4.3.11.Final 和 H2 1.3.172 数据库,我在一个缓慢的 linux 机器上分析我的应用程序,发现它在特定 SQL INSERT 上花费的时间比其他任何东西都多。似乎准备好的语句没有被缓存,因为准备好的语句的数量似乎与执行的语句数量大致相同。

我的解释是否正确(我正在使用 Yourkit Profiler)

我的 HibernateUtil 类配置如下

public static Configuration getInitializedConfiguration()
    {
        Configuration config = new Configuration();

        config.setProperty(Environment.DRIVER,"org.h2.Driver");
        config.setProperty(Environment.URL,"jdbc:h2:"+Db.DBFOLDER+"/"+Db.DBNAME+";FILE_LOCK=SOCKET;MVCC=TRUE;DB_CLOSE_ON_EXIT=FALSE;CACHE_SIZE=50000");
        config.setProperty(Environment.DIALECT,"org.hibernate.dialect.H2Dialect");
        System.setProperty("h2.bindAddress", InetAddress.getLoopbackAddress().getHostAddress());
        config.setProperty("hibernate.connection.username","jaikoz");
        config.setProperty("hibernate.connection.password","jaikoz");
        config.setProperty("hibernate.c3p0.numHelperThreads","10");
        config.setProperty("hibernate.c3p0.min_size","20");
        //Consider that if we have lots of busy threads waiting on next stages could we possibly have alot of active
        //connections.
        config.setProperty("hibernate.c3p0.max_size","200");
        config.setProperty("hibernate.c3p0.timeout","300");
        config.setProperty("hibernate.c3p0.maxStatementsPerConnection","50");
        config.setProperty("hibernate.c3p0.idle_test_period","3000");
        config.setProperty("hibernate.c3p0.acquireRetryAttempts","10");
        addEntitiesToConfig(config);
        return config;
    }

我想知道我是否配置错误,特别令人困惑的是 c3po 文档在某些参数的名称方面确实与 Hibernate 配置完全结合。

即它是 max_sizemax_pool_size

它是一个单用户多线程应用程序,理想情况下,我希望在应用程序期间缓存所有准备好的语句,因为只有大约 50 条不同的语句。

每次我都明白这一点

session = HibernateUtil.beginTransaction();

这将从池中获得一个连接,并且如果该特定连接先前已经准备好现在需要的语句,那么它可以使用该准备好的语句而无需编译新的语句。

如果准备好的语句不存在,则准备好。

如果这个连接已经有 50 个准备好的语句,那么最旧的语句将被丢弃。

这个占用更多时间的特定查询如下使用

public static void saveMatchedToRelease(Session session,Integer reportId, Integer recNo, SongFieldKey songFieldKey, SongChangeType type, String original, String edited)
{
    SongChanges sc = new SongChanges();
    sc.setReportId(reportId);
    sc.setRecNo(recNo);
    sc.setField(songFieldKey);
    sc.setType(type);
    sc.setOriginalValue(original);
    sc.setNewValue(edited);
    session.save(sc);
}

【问题讨论】:

  • 只是检查一下,因为它在屏幕截图中并不明显 - 你有 hibernate-c3p0 工件作为依赖项吗?在 Hibernate 的早期版本中,org.hibernate.c3p0.internal.C3P0ConnectionProvider 类在主要的hibernate.jar 中提供,因此许多 Hibernate/C3P0 指令没有提及额外的依赖关系。
  • @df778899 嗯,我不知道,我认为它会作为 Hibernate 的一部分包含在内,我是否必须明确添加它 - 我使用的是 maven?
  • 我希望如此 - hibernate-c3p0 不是 hibernate-core 的传递依赖。虽然再次查看屏幕截图,但它显示了来自 C3P0 的较低级别的NewProxyConnection 类等。我猜的另一种可能性是hibernate-core.jar 和较旧的hibernate.jar 都存在于依赖关系树的某个位置。如果这是针对较新的 Hibernate 获取过时的 C3P0ConnectionProvider,则可能无法通过设置。

标签: java hibernate profiler c3p0


【解决方案1】:

我认为缓存不是问题。如果您在每次插入时都打开一个新事务,并且总是使用不同的线程插入到您的歌曲表中,那么您可能会用打开的事务阻塞自己。多线程很容易导致错误,尤其是在开放式数据库事务中。

【讨论】:

    【解决方案2】:

    在 H2 中,准备好的语句在连接级别缓存。使用hibernate.c3p0.max_size=200,您有可能拥有如此多的打开连接,以至于用户每次执行操作时都会获得不同的 H2 连接。

    与其他 RDBMS 相比,本地内存 H2 的连接成本最低。尝试移除 C3P0 并使用单个 H2 连接进行测试。这应该确认准备好的语句被 JDBC 驱动程序缓存。

    在大多数情况下,连接越少越好。在您的情况下,对于单个用户和多个线程,您的机器不太可能有 200 个 CPU 来充分利用 hibernate.c3p0.max_size=200

    【讨论】:

    • 这是一个好消息,我已经大大减少了最大连接数,但不知道如何测试准备好的 staments 是否被重复使用。
    • 我不是在内存中使用 h2,而是基于磁盘的 h2,因为我使用数据库的全部原因是为了减少内存消耗。
    【解决方案3】:

    自 JDBC 3.0 起,将 setMaxStatements(n) 设置为 n 为正数将启用语句池,从而实现缓存。

    如果有人在使用 Oracle JDBC 驱动程序,您可以通过以下任何一种方法来验证缓存

    连接时,

    if (conn.getImplicitCachingEnabled())
      System.out.println("\nimplicit caching enabled"); 
    else
      System.out.println("\nimplicit caching disabled");
    

    关于声明,

    int creationState = stmt.creationState();
    switch(creationState) {
    case 0:
    System.out.println("\nCreation state: new");
    break;
    case 1:
    System.out.println("\nCreation state: from the implicit cache"); 
    break;
    case 2:
    System.out.println("\nCreation state: from the explicit cache"); 
    break;
    }
    

    参考:Oracle Statement Pooling and Caching

    【讨论】:

    • 问题是关于 H2 数据库,而不是 Oracle。
    猜你喜欢
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 2011-09-08
    • 1970-01-01
    • 2021-10-17
    • 2012-12-18
    • 2018-09-05
    相关资源
    最近更新 更多