2016-12-07 3 views
0

Was ist der beste Weg, um schnell einen großen Datensatz in SOLR zu erhalten?Schnell einen großen Datensatz in SOLR abrufen

Ich habe einen Index von 10 Millionen Datensätze (6 Zeichenfelder). Die Abfrage und der Filter, die ich benutze, bringt die Ergebnismenge auf 2,7 Millionen Datensätze herunter, die ich programmatisch durchsehen und die Daten für einen anderen Prozess bekommen möchte.

Momentan verwende ich SOLRJ und cursorMark, um 300000 Datensätze gleichzeitig zu erhalten. Jede Abfrage dauert 15-20 Sekunden. Gibt es eine Möglichkeit, die Geschwindigkeit zu verbessern? Die Größe der "Brocken" zu verringern schien keine Wirkung zu haben. Das Reduzieren von 300000 auf 50000 führte zu schnelleren Abfragen, aber es gab mehr von ihnen und die Gesamtzeit war äquivalent.

Das Problem, das ich denke, ist, dass SOLR das gesamte 2.7mil-Ergebnis erhalten muss und dann das Intervall, das bei jedem Anruf benötigt wird, aufteilen muss. Kombiniere das mit der "Größe" der Ergebnismenge und ich kann verstehen, warum es langsam ist. Ich bin auf der Suche nach ein paar Ideen zur Beschleunigung.

Mein SOLRJ Code ist unten:

Solr Version: 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 Ich habe versucht, die folgenden in einem Versuch, "Strom" die Daten aus solr. Leider ist die Abfrage selbst immer noch der Engpass, um die Daten zu erhalten. Sobald ich es habe, kann ich es schnell verarbeiten. Aber ich brauche immer noch einen schnelleren Weg, um die Daten zu bekommen.

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

Ich denke, Sie sollten in der Lage sein [verwenden Sie den Export-Request-Handler] (https://cwiki.apache.org/confluence/display/solr/Exporting+Result+Sets), also wenn Sie das noch nicht ausprobiert haben , sehen Sie, wie es funktioniert. Es wird intern in Solr als Backend für die Streaming-API usw. verwendet. – MatsLindh

+0

Ich konnte kein anständiges Beispiel für die Verwendung des Exportanforderungshandlers finden. Haben Sie zufällig einen Link, der zeigt, wie Sie das auf der Java-Seite oder mit SOLRJ verwenden würden? Ich versuchte eine andere Art des Streams (siehe Update in der Frage), aber es wird immer noch verlangsamt durch die erste Abfrage –

+0

Der Export-Befehl gibt immer json zurück, so dass Sie in der Lage sein sollten, eine HTTP-Anfrage und Deserialisierung des Inhalts schnell. SolrJ könnte vielleicht die neue Streaming-API verwenden, um etwas Ähnliches zu machen, aber ich kenne diesen Teil von SolrJ nicht. – MatsLindh

Antwort

0

MatsLindh Vorschlag für die Exportanforderung Handler funktionierte perfekt.

Dieses Request zu Ihrem solrconfig, wenn es nicht bereits vorhanden ist

<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> 

es dann nennt diese Art und Weise: /export q = rowID: [1 bis 4000] & fq = text: \“STUFF \“& fl = field1, field2 & sort = SortColumn asc

* Sie sind verpflichtet, eine sortieren und haben fl gesetzt

Jetzt habe ich nur n um herauszufinden, wie man den/Export in einem solrcloud-Setup zur Arbeit bringt.

Danke!

+0

Verwenden Sie die Streaming-API, um eine anständige SolrCloud-Unterstützung zu erhalten, da der/export-Endpunkt als Back-End in Ihrem Cluster verwendet wird - wenn Sie den Clusterstatus nicht implementieren und jeden Knoten selbst kontaktieren möchten. – MatsLindh

Verwandte Themen