在 SOLR 中快速检索大型数据集
Quickly retrieve a large dataset in SOLR
在 SOLR 中快速检索大型数据集的最佳方法是什么?
我有一个包含 1000 万条记录(6 个字符串字段)的索引。我正在使用的查询和过滤器将结果集减少到 270 万条记录,我想以编程方式对这些记录进行分页并为另一个进程获取数据。
目前我正在使用 SOLRJ 和 cursorMark 一次获取 300000 条记录。每个查询需要 15-20 秒。有没有办法提高速度?减小 "chunks" 的大小似乎没有效果。这意味着将 300000 减少到 50000 使查询速度更快,但查询更多,总时间是相等的。
我认为的问题是 SOLR 必须获取整个 270 万个结果集,然后分块出每次调用所需的时间间隔。将它与结果集的 "size" 结合起来,我就能理解为什么它很慢了。我正在寻找一些关于加快速度的想法。
我的 SOLRJ 代码如下:
Solr 版本:4.10.2
SolrQuery query = new SolrQuery();
query.setQuery("*:*");
query.setFilterQueries("text:\"*SEARCH STUFF*\"");
query.setParam("fl","id,srfCode");
query.setStart(0);
query.setRows(300000);
query.setSort("sortId", SolrQuery.ORDER.asc);
query.set("cursorMark", "*");
更新
我尝试了以下尝试 "stream" solr 中的数据。不幸的是,查询本身仍然是获取数据的瓶颈。一旦我有了它,我就可以快速处理它。但我仍然需要一种更快的方式来获取数据。
package org.search.builder;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.StreamingResponseCallback;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.common.SolrDocument;
import org.junit.Test;
public class SolrStream {
long startTime = 0;
long endTime = 0;
@Test
public void streaming() throws SolrServerException, IOException, InterruptedException {
long overallstartTime = System.currentTimeMillis();
startTime = System.currentTimeMillis();
HttpSolrServer server = new HttpSolrServer("https://solrserver/solr/indexname");
SolrQuery tmpQuery = new SolrQuery();
tmpQuery.setQuery("*:*");
tmpQuery.setFilterQueries("text:\"*SEARCH STUFF*\"");
tmpQuery.setParam("fl","id,srfCode");
tmpQuery.setStart(0);
tmpQuery.setRows(300000);
tmpQuery.set("cursorMark", "*");
//Sort needs to be unique or have tie breakers. In this case rowId will never be a duplicate
//If you can have duplicates then you need a tie breaker (sort should include a second column to sort on)
tmpQuery.setSort("rowId", SolrQuery.ORDER.asc);
final BlockingQueue<SolrDocument> tmpQueue = new LinkedBlockingQueue<SolrDocument>();
server.queryAndStreamResponse(tmpQuery, new MyCallbackHander(tmpQueue));
SolrDocument tmpDoc;
do {
tmpDoc = tmpQueue.take();
} while (!(tmpDoc instanceof StopDoc));
System.out.println("Overall Time: " + (System.currentTimeMillis() - overallstartTime) + " ms");
}
private class StopDoc extends SolrDocument {
// marker to finish queuing
}
private class MyCallbackHander extends StreamingResponseCallback {
private BlockingQueue<SolrDocument> queue;
private long currentPosition;
private long numFound;
public MyCallbackHander(BlockingQueue<SolrDocument> aQueue) {
queue = aQueue;
}
@Override
public void streamDocListInfo(long aNumFound, long aStart, Float aMaxScore) {
// called before start of streaming
// probably use for some statistics
currentPosition = aStart;
numFound = aNumFound;
if (numFound == 0) {
queue.add(new StopDoc());
}
}
@Override
public void streamSolrDocument(SolrDocument aDoc) {
currentPosition++;
if (queue.size() % 50000 == 0)
{
System.out.println("adding doc " + currentPosition + " of " + numFound);
System.out.println("Overall Time: " + (System.currentTimeMillis() - startTime) + " ms");
startTime = System.currentTimeMillis();
}
queue.add(aDoc);
if (currentPosition == numFound) {
queue.add(new StopDoc());
}
}
}
}
MatsLindh 对导出请求处理程序的建议非常有效。
将此 requestHandler 添加到您的 solrconfig 中(如果它尚不存在)
<requestHandler name="/export" class="solr.SearchHandler">
<lst name="invariants">
<str name="rq">{!xport}</str>
<str name="wt">xsort</str>
<str name="distrib">false</str>
</lst>
<arr name="components">
<str>query</str>
</arr>
</requestHandler>
然后这样称呼它:
/export?q=rowId:[1 TO 4000]&fq=text:\"STUFF\"&fl=field1,field2&sort=sortColumn asc
*您需要排序并设置 fl
现在我只需要弄清楚如何让 /export 在 solrcloud 设置中工作。
谢谢!
在 SOLR 中快速检索大型数据集的最佳方法是什么?
我有一个包含 1000 万条记录(6 个字符串字段)的索引。我正在使用的查询和过滤器将结果集减少到 270 万条记录,我想以编程方式对这些记录进行分页并为另一个进程获取数据。
目前我正在使用 SOLRJ 和 cursorMark 一次获取 300000 条记录。每个查询需要 15-20 秒。有没有办法提高速度?减小 "chunks" 的大小似乎没有效果。这意味着将 300000 减少到 50000 使查询速度更快,但查询更多,总时间是相等的。
我认为的问题是 SOLR 必须获取整个 270 万个结果集,然后分块出每次调用所需的时间间隔。将它与结果集的 "size" 结合起来,我就能理解为什么它很慢了。我正在寻找一些关于加快速度的想法。
我的 SOLRJ 代码如下:
Solr 版本:4.10.2
SolrQuery query = new SolrQuery();
query.setQuery("*:*");
query.setFilterQueries("text:\"*SEARCH STUFF*\"");
query.setParam("fl","id,srfCode");
query.setStart(0);
query.setRows(300000);
query.setSort("sortId", SolrQuery.ORDER.asc);
query.set("cursorMark", "*");
更新 我尝试了以下尝试 "stream" solr 中的数据。不幸的是,查询本身仍然是获取数据的瓶颈。一旦我有了它,我就可以快速处理它。但我仍然需要一种更快的方式来获取数据。
package org.search.builder;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.StreamingResponseCallback;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.common.SolrDocument;
import org.junit.Test;
public class SolrStream {
long startTime = 0;
long endTime = 0;
@Test
public void streaming() throws SolrServerException, IOException, InterruptedException {
long overallstartTime = System.currentTimeMillis();
startTime = System.currentTimeMillis();
HttpSolrServer server = new HttpSolrServer("https://solrserver/solr/indexname");
SolrQuery tmpQuery = new SolrQuery();
tmpQuery.setQuery("*:*");
tmpQuery.setFilterQueries("text:\"*SEARCH STUFF*\"");
tmpQuery.setParam("fl","id,srfCode");
tmpQuery.setStart(0);
tmpQuery.setRows(300000);
tmpQuery.set("cursorMark", "*");
//Sort needs to be unique or have tie breakers. In this case rowId will never be a duplicate
//If you can have duplicates then you need a tie breaker (sort should include a second column to sort on)
tmpQuery.setSort("rowId", SolrQuery.ORDER.asc);
final BlockingQueue<SolrDocument> tmpQueue = new LinkedBlockingQueue<SolrDocument>();
server.queryAndStreamResponse(tmpQuery, new MyCallbackHander(tmpQueue));
SolrDocument tmpDoc;
do {
tmpDoc = tmpQueue.take();
} while (!(tmpDoc instanceof StopDoc));
System.out.println("Overall Time: " + (System.currentTimeMillis() - overallstartTime) + " ms");
}
private class StopDoc extends SolrDocument {
// marker to finish queuing
}
private class MyCallbackHander extends StreamingResponseCallback {
private BlockingQueue<SolrDocument> queue;
private long currentPosition;
private long numFound;
public MyCallbackHander(BlockingQueue<SolrDocument> aQueue) {
queue = aQueue;
}
@Override
public void streamDocListInfo(long aNumFound, long aStart, Float aMaxScore) {
// called before start of streaming
// probably use for some statistics
currentPosition = aStart;
numFound = aNumFound;
if (numFound == 0) {
queue.add(new StopDoc());
}
}
@Override
public void streamSolrDocument(SolrDocument aDoc) {
currentPosition++;
if (queue.size() % 50000 == 0)
{
System.out.println("adding doc " + currentPosition + " of " + numFound);
System.out.println("Overall Time: " + (System.currentTimeMillis() - startTime) + " ms");
startTime = System.currentTimeMillis();
}
queue.add(aDoc);
if (currentPosition == numFound) {
queue.add(new StopDoc());
}
}
}
}
MatsLindh 对导出请求处理程序的建议非常有效。
将此 requestHandler 添加到您的 solrconfig 中(如果它尚不存在)
<requestHandler name="/export" class="solr.SearchHandler">
<lst name="invariants">
<str name="rq">{!xport}</str>
<str name="wt">xsort</str>
<str name="distrib">false</str>
</lst>
<arr name="components">
<str>query</str>
</arr>
</requestHandler>
然后这样称呼它: /export?q=rowId:[1 TO 4000]&fq=text:\"STUFF\"&fl=field1,field2&sort=sortColumn asc
*您需要排序并设置 fl
现在我只需要弄清楚如何让 /export 在 solrcloud 设置中工作。
谢谢!