2016-12-07 4 views
0

Каков наилучший способ быстро получить большой набор данных в SOLR?Быстрое извлечение большого набора данных в SOLR

У меня есть индекс 10 миллионов записей (6 строковых полей). В запросе и фильтре я получаю результат, равный 2,7 миллионам записей, которые я хотел бы программно пропустить и получить данные для другого процесса.

В настоящее время я использую SOLRJ и cursorMark для получения 300000 записей за раз. Каждый запрос занимает 15-20 секунд. Есть ли способ улучшить скорость? Уменьшение размера «кусков», похоже, не имело эффекта. Значение, уменьшающее 300000 до 50000, делало запросы быстрее, но их было больше, и общее время было эквивалентным.

Проблема, я думаю, заключается в том, что SOLR должен получить весь набор результатов 2.7mil, а затем вырезать требуемый интервал для каждого вызова. Объедините это с «размером» набора результатов, и я могу понять, почему он медленный. Я ищу некоторые идеи по его ускорению.

Мой 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", "*"); 

UPDATE Я попытался следующие в попытке "поток" данные из 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()); 
      } 
     } 
     } 
} 
+3

Я думаю, вы должны иметь возможность использовать обработчик запроса экспорта (https://cwiki.apache.org/confluence/display/solr/Exporting+Result+Sets), поэтому, если вы еще не пробовали это , см., как это работает. Он используется в качестве бэкэнда для потокового api и т. Д. Внутри Solr. – MatsLindh

+0

Я не мог найти достойный пример использования обработчика запроса экспорта. У вас есть ссылка, которая показывает, как вы будете использовать это на стороне Java или в SOLRJ? Я попробовал другой способ потоковой передачи (см. Обновление в вопросе), но он по-прежнему замедляется первоначальным запросом. –

+0

Команда export всегда возвращает json, поэтому вы сможете быстро сделать HTTP-запрос и десериализовать контент. SolrJ может использовать новый потоковый api, чтобы сделать что-то подобное, но я не знаком с этой частью SolrJ. – MatsLindh

ответ

0

Предложение 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> 

Затем вызовите его таким образом: /экспорт д = RowId: [1 TO 4000] & FQ = текст: \»STUFF \»& фл = field1, field2 & сортировки = sortColumn возрастанию

* Вы обязаны сортировать и иметь фл набор

Теперь я просто п чтобы выяснить, как заставить/export работать в настройке solrcloud.

Спасибо!

+0

Используйте Streaming API, чтобы получить приличную поддержку SolrCloud, так как в качестве backend вашего кластера используется конечная точка/export, если вы не хотите реализовывать разборе состояния кластера и сами связываться с каждым узлом. – MatsLindh

Смежные вопросы