SOLR - Най-добрият подход за импортиране на 20 милиона документа от csv файл

Сегашната ми задача е да разбера най-добрия подход за зареждане на милиони документи в solr. Файлът с данни е експортиран от DB във формат csv.

В момента обмислям да разделя файла на по-малки файлове и да имам скрипт, докато публикувам тези по-малки с помощта на curl.

Забелязах, че ако публикувате голямо количество данни, през повечето време заявката изтича.

Разглеждам Data importer и изглежда като добър вариант

Всички други идеи са високо оценени

Благодаря


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 манипулатора, ако имате достъп до DB. - person Mark O'Connor; 26.02.2012

В SOLR 4.0 (понастоящем в BETA), CSV от локална директория могат да бъдат импортирани директно с помощта на UpdateHandler. Промяна на примера от SOLR Wiki

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

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

person busybee    schedule 11.10.2012
comment
Каква е производителността на UpdateHandler спрямо DataImportHandler? Входът е CSV и в двата случая. - person zengr; 22.06.2013
comment
Не съм правил никакви бенчмаркове, но производителността на DataImportHandler е доста добра. Направихме около 20 милиона записа, което доведе до индекс от приблизително 7 GB (след оптимизация) за около час. Също така трябваше да изпълним някои трансформации на данните, преди да ги добавим към индекса - така че всъщност не можахме да го направим с помощта на UpdateHandler. - person busybee; 26.07.2013
comment
Благодаря! Аз също правя това и работи като чар. около 50 милиона записа (размер 8gb) за ~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: Няма налични живи SolrServers за обработка на тази заявка

person Rahul Sharma    schedule 13.09.2016

Определено първо ги заредете в нормална база данни. Има всякакви инструменти за работа с CSV файлове (например postgres' COPY), така че трябва да е лесно. Използването на Data Import Handler също е доста просто, така че това изглежда като най-безпроблемния начин за зареждане вашите данни. Този метод също ще бъде по-бърз, тъй като няма да имате ненужни мрежови/HTTP разходи.

person beerbajay    schedule 25.02.2012
comment
Файловете се изтеглят от DB. Не сте сигурни какъв би бил смисълът да ги зареждате обратно? - person Bobby ...; 26.02.2012
comment
Добре, тогава просто използвайте Data Import Handler, за да ги прочетете директно. Има ли нещо нередно в тази опция? - person beerbajay; 26.02.2012
comment
+1 Направих няколко бързи теста за производителност и DIH превъзхожда груповите ангажименти с порядък. Но това е само първо впечатление. - person miku; 09.03.2013
comment
DIH не се справи с изтеглянето на огромни количества данни, когато DB беше на различно мрежово местоположение от мястото, където е инсталиран Solr. Последва изчакване на връзката на гнездото. Трябваше да изтегля данните от DB в csv файлове на по-малки парчета с помощта на opencsv. След това използвах FileListEntityProcessor и LineEntityProcessor за индексиране на данните в Solr. - person Vijay; 18.01.2014
comment
@Vijay Това звучи като по-скоро проблем с вашата мрежова инфраструктура/конфигурация на DB, отколкото с DIH или Solr. - person beerbajay; 13.02.2014
comment
@beerbajay Извадили ли сте 20 милиона записа от таблица с DIH? Продължавам да чета, че има и много други проблеми с DIH. - person Vijay; 13.02.2014

Справочното ръководство казва, че ConcurrentUpdateSolrServer може/трябва да се използва за групови актуализации.

Javadocs са донякъде неправилни (v 3.6.2, версия 4.7.0):

ConcurrentUpdateSolrServer буферира всички добавени документи и ги записва в отворени HTTP връзки.

Не буферира за неопределено време, а до int queueSize, което е параметър на конструктора.

person milan    schedule 31.03.2014