2016-12-07 9 views
0

SOLRで大量のデータセットをすばやく取得する最もよい方法は何ですか。SOLRで大きなデータセットをすばやく取得する

私は1000万レコード(6文字フィールド)のインデックスを持っています。私が使用しているクエリとフィルタは、270万レコードに設定された結果を取得し、プログラムでページを切り替えて別のプロセスのデータを取得したいと考えています。

現在、私は一度に300000レコードを取得するためにSOLRJとcursorMarkを使用しています。各クエリには15〜20秒かかります。速度を向上させる方法はありますか? 「チャンク」のサイズを小さくすると効果がないようです。 500000に300000を減らす意味は、クエリーを速くしましたが、より多くのものがあり、全体の時間は同等でした。

私が思う問題は、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)できるはずです。まだ試していないのであればそれがどのように実行されるかを見てください。これは、Solrの内部でストリーミングAPIなどのバックエンドとして使用されています。 – MatsLindh

+0

エクスポート要求ハンドラの使用例がまったく見つかりませんでした。 Java側やSOLRJ上でどのように使用するかを示すリンクがありますか? ストリーミングの別の方法(質問の更新を参照)を試みましたが、まだ初期クエリによって遅くなっています –

+0

エクスポートコマンドは常にjsonを返します。したがって、http要求を行い、内容を素早くデシリアライズできるはずです。 SolrJは新しいストリーミングAPIを使って同様のことをすることができるかもしれませんが、私はSolrJのその部分に慣れていません。 – MatsLindh

答えて

0

MatsLindhの提案が完全に機能しました。

あなた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> 

いない場合、その後、このようにそれを呼び出す:? /輸出Q = ROWID:[1〜4000] =テキスト& FQ:」\を「& FL =フィールド1、フィールド2 &ソート= sortColumn昇順

\ STUFFあなたが

今私だけのnを設定FL並べ替えるとが要求されています*/exportをsolrcloudセットアップで動作させる方法を理解するためにeedを使用してください。

ありがとうございます!

+0

Streaming APIを使用すると、クラスタの状態を解析して各ノードに自分自身で連絡することを望まない場合、クラスタ全体で/ exportエンドポイントをバックエンドとして使用するため、まともなSolrCloudサポートを利用できます。 – MatsLindh

関連する問題