高性能休眠插入

luk*_*uke 16 java performance hibernate3

我正在处理应用程序的延迟敏感部分,基本上我将收到一个网络事件转换数据,然后将所有数据插入到数据库中.在分析后,我发现基本上所有的时间都花在尝试保存数据上.这是代码

private void insertAllData(Collection<Data> dataItems)
{
    long start_time = System.currentTimeMillis();
    long save_time = 0;
    long commit_time = 0;
    Transaction tx = null;
    try
    {
        Session s = HibernateSessionFactory.getSession();
        s.setCacheMode(CacheMode.IGNORE);
        s.setFlushMode(FlushMode.NEVER);
        tx = s.beginTransaction();
        for(Data data : dataItems)
        {
            s.saveOrUpdate(data);
        }
        save_time = System.currentTimeMillis();
        tx.commit();
        s.flush();
        s.clear();
    }
    catch(HibernateException ex)
    {
        if(tx != null)
            tx.rollback();
    }
    commit_time = System.currentTimeMillis();
    System.out.println("Save: " + (save_time - start_time));
    System.out.println("Commit: " + (commit_time - save_time));
    System.out.println();
}
Run Code Online (Sandbox Code Playgroud)

集合的大小总是小于20.这是我看到的时间数据:

Save: 27
Commit: 9

Save: 27
Commit: 9

Save: 26
Commit: 9

Save: 36
Commit: 9

Save: 44
Commit: 0
Run Code Online (Sandbox Code Playgroud)

这对我来说很困惑.我认为save应该快速,所有的时间都应该用在上面commit.但显然我错了.我也尝试删除事务(它不是真的必要)但我看到更糟糕的时候...我已经设置了hibernate.jdbc.batch_size = 20 ...

我可以期望获得多达500条消息/秒,所以我需要单个消息处理不到20毫秒.

我需要这个操作尽可能快,理想情况下只有一次往返数据库.我怎样才能做到这一点?

Mic*_*ael 16

将主键生成从服务器端自动递增移开.您的Java代码必须负责PK生成以避免往返.

对于体面的批量插入性能,您需要一种方法,在每次调用saveOrUpdate时都不需要访问数据库.使用UUID作为主键,或实现HiLo可以帮助实现这一目标.否则,实际上没有批量插入.

为了兼顾其他外部系统的性能和互操作性,池化池化优化器是最佳选择.