需求
有100个core,每个core4000w数据量。把所有数据导出来。
方案1.
直接对每个core通过HttpSolrClient先取出总条数,然后通过每次分页读n行,直到读完,这个方案肯定不行,因为越到后面,读取速度越慢,不用想都要很长时间。
方案2.
深度分页
通过游标,可以使分页速度很快。
SolrQuery solrQuery = new SolrQuery();
solrQuery.setQuery("*:*");
solrQuery.setFields("*");
solrQuery.addSort("uid", ORDER.asc);
String cursorMark = CursorMarkParams.CURSOR_MARK_START;
solrQuery.setRows(config.getBlockSize());
boolean done = false;
while (!done) {
solrQuery.set(CursorMarkParams.CURSOR_MARK_PARAM, cursorMark);
QueryResponse rsp = client.query(solrQuery);
String nextCursorMark = rsp.getNextCursorMark();
SolrDocumentList results = rsp.getResults();
for (SolrDocument d : results) {
}
if (nextCursorMark == null || cursorMark.equals(nextCursorMark)) {
done = true;
}
cursorMark = nextCursorMark;
}
但是发现每次查询都很慢,qtime基本都在1s以内,但是拿到QueryResponse要1分钟。不知道为什么。网上说qtime只是返回所以数据id的时间,但是返回数据还要时间
方案3
通过EmbeddedSolrServer提取
这个是比较底层的操作,也是先得到总条数,然后通过每次分页读n行,直到读完。
进过测试一小时700多万条数据输出,但是也越往后越慢,一个core执行完需要15小时
方案4
直接lucene读取
lucene也有两种,一种是直接读取全部数据放内存,说是速度很快,但是内存占用太大。所以还是用luncene的分页算法。
Directory dir = FSDirectory.open(Paths.get(corepath, key, "data/index"));
IndexReader indexReader = DirectoryReader.open(dir);
Query query = new MatchAllDocsQuery();
IndexSearcher searcher = new IndexSearcher(indexReader);
int pageStart = 0;
ScoreDoc lastBottom = null;
int count = 0;
while (pageStart < 100000000) {//10000000足够大就行
TopDocs tds = searcher.searchAfter(lastBottom, query, 50000);
if (tds.scoreDocs.length == 0) {
break;
}
pageStart += tds.scoreDocs.length;
lastBottom = tds.scoreDocs[tds.scoreDocs.length - 1];
List<String> list = new ArrayList<String>();
for (ScoreDoc sc : tds.scoreDocs) {
Document doc = searcher.doc(sc.doc);
String uid = doc.get("uid"));
//....
count += 50000;
System.out.println("--------------------------------" + count);
}
indexReader.close();
dir.close();
System.out.println(key + "end.................");
这个方法一个core几十分钟就搞定了