SOLR - лучший подход для импорта 20 миллионов документов из CSV-файла

Моя текущая задача — найти лучший способ загрузки миллионов документов в solr. Файл данных представляет собой экспорт из БД в формате csv.

В настоящее время я думаю о том, чтобы разбить файл на более мелкие файлы и создать сценарий для публикации этих более мелких файлов с помощью curl.

Я заметил, что если вы отправляете большое количество данных, большую часть времени запрос истекает.

Я изучаю импортер данных, и это кажется хорошим вариантом.

Любые другие идеи высоко ценятся

Спасибо


person Bobby ...    schedule 25.02.2012    source источник


Ответы (5)


Если база данных уже не является частью вашего решения, я бы не усложнял его. Цитируя Часто задаваемые вопросы SOLR, это ваш контейнер сервлета, который выдает время ожидания сеанса.

Как я вижу, у вас есть несколько вариантов (в моем порядке предпочтения):

Увеличить время ожидания контейнера

Увеличьте время ожидания контейнера. (параметр "maxIdleTime", если вы используете встроенный экземпляр Jetty).

Я предполагаю, что вы только изредка индексируете такие большие файлы? Временное увеличение тайм-аута может быть просто самым простым вариантом.

Разделить файл

Вот простой скрипт unix, который выполнит эту работу (разделив файл на 500 000 строк):

split -d -l 500000 data.csv split_files.
for file in `ls split_files.*`
do  
curl 'http://localhost:8983/solr/update/csv?fieldnames=id,name,category&commit=true' -H 'Content-type:text/plain; charset=utf-8' --data-binary @$file
done

Разобрать файл и загрузить кусками

Следующий groovy-скрипт использует opencsv и solrj для анализа CSV-файла и фиксации изменений в Solr каждые 500 000 строк.

import au.com.bytecode.opencsv.CSVReader

import org.apache.solr.client.solrj.SolrServer
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer
import org.apache.solr.common.SolrInputDocument

@Grapes([
    @Grab(group='net.sf.opencsv', module='opencsv', version='2.3'),
    @Grab(group='org.apache.solr', module='solr-solrj', version='3.5.0'),
    @Grab(group='ch.qos.logback', module='logback-classic', version='1.0.0'),
])

SolrServer server = new CommonsHttpSolrServer("http://localhost:8983/solr/");

new File("data.csv").withReader { reader ->
    CSVReader csv = new CSVReader(reader)
    String[] result
    Integer count = 1
    Integer chunkSize = 500000

    while (result = csv.readNext()) {
        SolrInputDocument doc = new SolrInputDocument();

        doc.addField("id",         result[0])
        doc.addField("name_s",     result[1])
        doc.addField("category_s", result[2])

        server.add(doc)

        if (count.mod(chunkSize) == 0) {
            server.commit()
        }
        count++
    }
    server.commit()
}
person Mark O'Connor    schedule 26.02.2012
comment
Марк, спасибо за подробный ответ. Это соответствует тому, что я пытался выяснить. У меня будут огромные нагрузки в качестве новичков, и я буду обновлять дельты каждый час или около того. Кажется, я знаю варианты первой загрузки. Тем не менее, я не уверен, что будет наилучшим управляемым процессом для обновлений. Я ищу настраиваемый надежный процесс обновления. Любая информация вокруг этого будет высоко оценена. Спасибо. - person Bobby ...; 26.02.2012
comment
Я бы предложил входной каталог для новых файлов и переместил файлы в обработанный каталог после индексации. Просто и легко поддерживать... Однако.... Вы сказали, что файлы CSV поступают из базы данных? В этом случае, возможно, вам лучше использовать обработчик DIH, если у вас есть доступ к БД. - person Mark O'Connor; 26.02.2012

В SOLR 4.0 (в настоящее время в бета-версии) файлы CSV из локального каталога можно импортировать напрямую с помощью UpdateHandler. Изменение примера из вики SOLR

curl http://localhost:8983/solr/update?stream.file=exampledocs/books.csv&stream.contentType=text/csv;charset=utf-8

И это передает файл из локального местоположения, поэтому нет необходимости разбивать его на части и отправлять через HTTP.

person busybee    schedule 11.10.2012
comment
Какова производительность UpdateHandler по сравнению с DataImportHandler? Входные данные — CSV в обоих случаях. - person zengr; 22.06.2013
comment
Я не проводил никаких тестов, но производительность DataImportHandler довольно высока. Мы сделали около 20 миллионов записей, в результате чего индекс составил примерно 7 ГБ (после оптимизации) примерно за час. Также нам пришлось выполнить некоторые преобразования данных перед добавлением их в индекс, поэтому мы не могли сделать это с помощью UpdateHandler. - person busybee; 26.07.2013
comment
Спасибо! Я тоже делаю это, и это работает как шарм. около 50 миллионов записей (размер 8 ГБ) за ~ 40 минут. - person zengr; 26.07.2013

Приведенные выше ответы очень хорошо объяснили стратегии приема с одной машины.

Еще несколько вариантов, если у вас есть инфраструктура больших данных и вы хотите внедрить распределенный конвейер приема данных.

  1. Используйте sqoop, чтобы передать данные в hadoop, или вручную поместите свой CSV-файл в hadoop.
  2. Используйте один из следующих коннекторов для приема данных:

соединитель hive-solr, коннектор Spark-solr.

PS:

  • Убедитесь, что брандмауэр не блокирует подключение между клиентскими узлами и узлами solr/solrcloud.
  • Выберите правильную фабрику каталогов для приема данных, если поиск почти в реальном времени не требуется, используйте StandardDirectoryFactory.
  • Если во время приема в журналах клиентов вы получаете исключение ниже, настройте конфигурацию autoCommit и autoSoftCommit в файле solrconfig.xml.

SolrServerException: нет доступных активных серверов SolrServer для обработки этого запроса

person Rahul Sharma    schedule 13.09.2016

Определенно просто сначала загрузите их в обычную базу данных. Существуют всевозможные инструменты для работы с CSV (например, postgres' COPY), так что это должно быть легко. Использование обработчика импорта данных также довольно просто, поэтому кажется, что это самый простой способ загрузки ваши данные. Этот метод также будет быстрее, поскольку у вас не будет ненужных сетевых/HTTP-накладных расходов.

person beerbajay    schedule 25.02.2012
comment
Файлы вытаскиваются из БД. Не уверен, какой смысл загружать их обратно? - person Bobby ...; 26.02.2012
comment
Хорошо, тогда просто используйте обработчик импорта данных, чтобы прочитать их напрямую. Что-то не так с этим вариантом? - person beerbajay; 26.02.2012
comment
+1 Я провел несколько быстрых тестов производительности, и DIH на порядок превосходит массовые коммиты. Но это только первое впечатление. - person miku; 09.03.2013
comment
DIH не справлялся с извлечением огромных объемов данных, когда БД находилась в другом сетевом расположении, а не в том, где был установлен Solr. Возникло время ожидания подключения к сокету. Пришлось извлекать данные из БД в CSV-файлы меньшими фрагментами, используя opencsv. Затем использовал FileListEntityProcessor и LineEntityProcessor для индексации данных в Solr. - person Vijay; 18.01.2014
comment
@Vijay Это больше похоже на проблему с вашей сетевой инфраструктурой / конфигурацией БД, чем с DIH или Solr. - person beerbajay; 13.02.2014
comment
@beerbajay Вы вытащили 20 миллионов записей из таблицы с DIH? Я продолжаю читать, что с DIH тоже есть масса других проблем. - person Vijay; 13.02.2014

Справочное руководство говорит ConcurrentUpdateSolrServer может/должен использоваться для массовых обновлений.

Javadocs несколько неверны (v 3.6.2, v 4.7.0):

ConcurrentUpdateSollServer буферизует все добавленные документы и записывает их в открытые HTTP-соединения.

Он буферизуется не бесконечно, а до int queueSize, который является параметром конструктора.

person milan    schedule 31.03.2014