在 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 设置中工作。

谢谢!