【问题标题】:SOLR - Best approach to import 20 million documents from csv fileSOLR - 从 csv 文件导入 2000 万个文档的最佳方法
【发布时间】:2012-03-15 23:47:31
【问题描述】:

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

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

我注意到,如果您发布大量数据,大多数情况下请求都会超时。

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

任何其他想法高度赞赏

谢谢

【问题讨论】:

    标签: csv import solr bulkinsert dataimporthandler


    【解决方案1】:

    除非数据库已经是您解决方案的一部分,否则我不会为您的解决方案增加额外的复杂性。引用 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()
    }
    

    【讨论】:

    • 马克,感谢您的详细回答。这与我试图弄清楚的一致。作为初学者,我将承受巨大的负担,并且每小时左右更新一次增量。我想我知道第一次加载的选项。但是,我不确定更新的最佳可管理过程是什么。我正在寻找可配置的强大更新过程。任何有关这方面的信息将不胜感激。谢谢。
    • 我建议为新文件创建一个“输入”目录,并在索引后将文件移动到“已处理”目录中。简单且易于维护.... 但是.... 您说 CSV 文件来自数据库?在这种情况下,如果您有权访问数据库,则可能需要更好地使用 DIH 处理程序。
    【解决方案2】:

    在 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 发布。

    【讨论】:

    • UpdateHandler 与 DataImportHandler 的性能如何?在这两种情况下,输入都是 CSV。
    • 我没有运行任何基准测试,但 DataImportHandler 的性能相当不错。我们在大约一个小时内处理了大约 2000 万条记录,从而产生了大约 7GB(优化后)的索引。此外,在将数据添加到索引之前,我们必须对数据进行一些转换 - 所以无法使用 UpdateHandler 真正做到这一点。
    • 谢谢!我也在做这个,它就像一个魅力。大约 50M 条记录(大小 8gb)在约 40 分钟内。
    【解决方案3】:

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

    如果您拥有大数据基础架构并希望实施分布式数据摄取管道,则几乎没有其他选择。

    1. 使用 sqoop 将数据带到 hadoop 或手动将 csv 文件放入 hadoop。
    2. 使用以下连接器之一提取数据:

    hive- solr connector, spark- solr connector.

    PS:

    • 确保没有防火墙阻止客户端节点和 solr/solrcloud 节点之间的连接。
    • 选择正确的目录工厂进行数据摄取,如果不需要近乎实时的搜索,则使用StandardDirectoryFactory
    • 如果在摄取期间客户端日志中出现以下异常,请在 solrconfig.xml 文件中调整 autoCommitautoSoftCommit 配置。

    SolrServerException: 没有可用的实时 SolrServers 来处理这个 请求

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 正在从数据库中提取文件。不确定将它们加载回来有什么意义?
      • 好的,那就直接用Data Import Handler 把它们读出来。这个选项有问题吗?
      • +1 我做了一些快速的性能测试,DIH 的性能优于批量提交一个数量级。但这只是第一印象。
      • 当数据库位于与安装 Solr 的位置不同的网络位置时,DIH 无法处理提取大量数据。随后发生套接字连接超时。必须将数据从数据库中提取到较小的 csv 文件中使用 opencsv 的块。然后使用 FileListEntityProcessor 和 LineEntityProcessor 将数据索引到 Solr。
      • @Vijay 这听起来更像是网络基础设施/数据库配置的问题,而不是 DIH 或 Solr。
      【解决方案5】:

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

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

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

      它不会无限期地缓冲,而是直到int queueSize,这是一个构造函数参数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-09
        • 1970-01-01
        • 2017-03-11
        • 2023-03-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多