什么是写入数据加载器的最佳方式?

什么是写入数据加载器的最佳方式?

问题描述:

我正在使用Spring 2.5以及与之配合的Hibernate。我正在运行Oracle 11g数据库。什么是写入数据加载器的最佳方式?

我创建了扩展HibernateTemplate的DAO。现在我想写一个装载器,在我的人员表中插入500万行。我以一种简单的方式写下了这些内容,比如从CSV文件中读取一行,将它变成一个人,保存到表格中。继续操作直到CSV文件为空。

问题是我耗尽了大约450000行的堆空间。所以我把内存的大小从1024米增加到了2048米,现在我在大约900000行之后耗尽了内存。

Hmmmmm ....

所以,我读过有关关闭查询缓存Hibernate的一些东西,但我不使用二级缓存,所以我不认为这是问题。

我读过一些关于JDBC2批处理的东西,但我不认为这适用于hibernate。

所以,我想知道是否有关于Hibernate的基本知识,我错过了。

+1

这实际上只是一个从csv读取并加载到表中的问题,或者您是否在执行其他一些处理?如果它是前者并且这是一次性静态数据加载,那么我会推荐使用批量加载器(如Oracle sqlldr)。 – DaveRlz

+1

@DaveRlz除了有两个表正在加载,我没有做任何其他处理。但我希望我的解决方案独立于数据库。 – Thom

+2

如果只有文档有......等等,它就在那里:http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#batch-inserts,http://docs.jboss .org/hibernate/core/3.6/reference/en-US/html_single /#batch-statelesssession –

说实话我不会为此使用hibernate。 ORM的设计不是为了将数百万行装载到数据库中。不是说你做不到,但有点像用电钻挖一个游泳池;你会使用挖掘机,而不是演习。

就你而言,我会用数据库附带的加载器应用程序直接将CSV加载到数据库。如果你不想这样做,是的,批量插入将会更有​​效率。尽管如此,我认为Hibernate不会让你这么做。如果我是你,我只需要使用普通的JDBC,或者至多Spring JDBC。

如果你在实体中有复杂的业务逻辑并且绝对必须使用Hibernate,那么你可以按Richard的建议刷新每N个记录。不过,我认为这是一个非常糟糕的黑客攻击。

根据我使用EclipseLink的经验,在插入/更新时保持单个事务处于打开状态,许多会记录您遇到的症状。

您正在使用EntityManager(某种类型,JPA或Hybernate特定 - 它仍在管理Entity s)。它试图将工作集保存在内存中,用于交易的整个生命周期。

一般的解决方案是提交&,每N次插入后重新启动事务;对我来说是典型的n为1000


作为一个注脚,一些版本(不确定的,它是一个几年)的EclipseLink,会话冲洗/清除并没有解决这个问题。

这听起来像是由于第一级缓存(Hibernate会话)而导致空间不足。您可以定期刷新Hibernate会话以减少内存使用量。但是像这样使用Hibernate进行加载任务将会很慢,因为JDBC很慢。如果你有一个好主意,环境会是什么样子,你对数据量有一个限制,并且你有足够大的窗口进行处理,然后你可以管理,但是在你希望它工作在多个不同的客户端网站,并且希望尽量减少由于某些客户端网站的加载作业无法解决问题而花费的时间,那么您应该使用数据库的批量复制工具。批量复制方法意味着数据库将暂停所有的约束检查和索引构建以及事务日志记录,而不是集中于尽可能快地提供数据。由于JDBC没有像数据库那样获得这种级别的合作,所以它无法竞争。在之前的工作中,我们用花了20分钟的SQLLoader任务取代了一个需要8个小时才能运行的JDBC加载器任务。你可以牺牲数据库的独立性,但是所有的数据库都有一个批量拷贝工具(因为DBA依赖于它们),所以你将对每个数据库有一个非常相似的进程,只有你调用的exe文件格式是指定应该改变。这样你就可以充分利用你的处理窗口。