Каков наилучший способ быстро получить большой набор данных в 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());
}
}
}
}
Я думаю, вы должны иметь возможность использовать обработчик запроса экспорта (https://cwiki.apache.org/confluence/display/solr/Exporting+Result+Sets), поэтому, если вы еще не пробовали это , см., как это работает. Он используется в качестве бэкэнда для потокового api и т. Д. Внутри Solr. – MatsLindh
Я не мог найти достойный пример использования обработчика запроса экспорта. У вас есть ссылка, которая показывает, как вы будете использовать это на стороне Java или в SOLRJ? Я попробовал другой способ потоковой передачи (см. Обновление в вопросе), но он по-прежнему замедляется первоначальным запросом. –
Команда export всегда возвращает json, поэтому вы сможете быстро сделать HTTP-запрос и десериализовать контент. SolrJ может использовать новый потоковый api, чтобы сделать что-то подобное, но я не знаком с этой частью SolrJ. – MatsLindh