SOLR - 从csv文件导入2000万个文档的最佳方法

时间:2012-02-25 23:47:36

标签: csv import solr bulkinsert dataimporthandler

我目前的任务是找出在solr中加载数百万个文档的最佳方法。 数据文件是以csv格式从DB导出的。

目前,我正在考虑将文件拆分为较小的文件并使用脚本,同时使用curl发布这些较小的文件。

我注意到如果您发布大量数据,大部分时间请求都会超时。

我正在研究数据导入器,它似乎是一个不错的选择

高度赞赏任何其他想法

由于

5 个答案:

答案 0 :(得分:22)

除非数据库已经是您解决方案的一部分,否则我不会为您的解决方案增加额外的复杂性。引用SOLR FAQ它是发出会话超时的servlet容器。

在我看来,你有几个选择(按我的偏好顺序):

增加容器超时

增加容器超时。 (“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文件,并每隔500,000行将更改提交给Solr。

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()
}

答案 1 :(得分:12)

在SOLR 4.0(目前在BETA中)中,可以使用UpdateHandler直接导入本地目录中的CSV。修改the SOLR Wiki

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

这会从本地位置传输文件,因此无需将其整理并通过HTTP发布。

答案 2 :(得分:3)

以上答案已经很好地解释了单机的摄取策略。

如果您拥有大型数据基础架构并希望实现分布式数据提取管道,则可以选择更多选项。

  1. 使用sqoop将数据传输到hadoop或将您的csv文件手动放入hadoop。
  2. 使用以下连接器之一来提取数据:
  3. hive- solr connectorspark- solr connector

    PS:

    • 确保没有防火墙阻止客户端节点和solr / solrcloud节点之间的连接。
    • 选择正确的目录工厂进行数据提取,如果不需要近实时搜索,则使用StandardDirectoryFactory
    • 如果您在提取过程中在客户端日志中遇到异常,请调整autoCommit文件中的autoSoftCommitsolrconfig.xml配置。
      

    SolrServerException:没有可用于处理此问题的实时SolrServers   请求

答案 3 :(得分:1)

绝对只是先将它们加载到普通数据库中。有各种各样的工具来处理CSV(例如,postgres' COPY),所以应该很容易。使用Data Import Handler也非常简单,因此这似乎是加载数据最无摩擦的方式。此方法也会更快,因为您不会有不必要的网络/ HTTP开销。

答案 4 :(得分:-1)

The reference guide says ConcurrentUpdateSolrServer可以/应该用于批量更新。

Javadocs有些不正确(v 3.6.2v 4.7.0):

  

ConcurrentUpdateSolrServer缓冲所有添加的文档,并将它们写入打开的HTTP连接。

它不会无限期地缓冲,但最多为int queueSize缓冲区,这是一个构造函数参数。