日期:2014-05-16  浏览次数:20501 次

新手学搜索之从数据库导入大量数据而导致内存溢出问题解决(转)

?

?

http://guoyunsky.iteye.com/blog/759148

??????Solr有个很方便的处理器叫DataImportHandler,可以通过配置配置db-data-config.xml配置各种数据源然后
从中导入数据进行索引,很方便我们进行开发.但是之前从数据库导入数据一直有个问题,就是如果数据库中数据过大,就会导致内存溢出.自己经过阅读源码以及发邮件到Solr邮件列表,终于找到了解决办法,这里拿出来共享.
????? 这里我的Solr版本是Solr1.4.0,数据库是Sql Server2005.其他数据库可能有些不适用(请在其他数据库运行成功的同学也分享下),但根据这个思路应该都有自己的解决方案.
????? DataImportHandler中从数据库导入数据进行索引主要通过JDBC进行处理.由于自己对JDBC的认识浅薄,一直认为JDBC是一次性将要查询的数据从数据库中数据读取过去.但没有想到其实从数据库获取数据其实也是以流的形式,可以一段段的获取.也就是可以在客户端每获取一条再从流中取新的一条数据如此取完为止(这里感谢高手提示).由于使用的数据库是Sql Server2005,本想通过它的sqljdbc.jar中获取些提示(尝试下源码没有成功),从Jar中大概发现Sql Server有这样的设置,于是上微软官网的MSDN获取到了答案(
URL:http://msdn.microsoft.com/zh-cn/library/ms378663(SQL.90).aspx):

??????Sets the default cursor type that is used for all result sets that are created by using this SQLServerDataSource object.
??复制
??????? public void setSelectMethod(java.lang.String selectMethod)
??参数
??????? selectMethod
??????? A String value that contains the default cursor type.
??备注
?????? The selectMethod is the default cursor type that is used for a result set. This property is useful when you are dealing with large result? sets and do not want to store the whole result set in memory on the client side. By setting the property to "cursor," you can create a? server-side cursor that can fetch smaller chunks of data at a time. If the selectMethod property is not set, getSelectMethod returns the? default value of "direct".

?

???? 同时这样做的话也要设置Connection的两个属性:ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY.但跟踪源码发现Solr中已经有这样的设置.于是可以直接在db-data-config.xml中配置即可完成,具体配置如下:

<dataSource name="dsSqlServer" type="JdbcDataSource" driver="com.microsoft.sqlserver.jdbc.SQLServerDriver" batchSize="3000" url="jdbc:sqlserver://192.168.1.5:1433; DatabaseName=testDatabase;responseBuffering=adaptive;selectMethod=cursor" user="sa" password="12345" />


? ? 其中只要在URL中加上responseBuffering=adaptive;selectMethod=cursor即可,无论多大的表根据这个配置Solr都可以从中读取数据并索引完成,当然,前提是不发生什么故障,如网络故障.这一想法也得到了Solr开发人员的验证,以下是他们给我回复的邮件:
??????
That's not really true. DataImportHandler streams the result from database query and adding documents into index. So it shouldn't load all database data into memory. Disabling autoCommit, warming queries and spellcheckers usually decreases required amount of memory during
??indexing process.Please share your hardware details, jvm options, solrconfig and schema configuration, etc.

?