14

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

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

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

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

任何其他想法高度赞赏

谢谢

4

5 回答 5

21

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

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

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

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

于 2012-10-11T14:26:38.077 回答
3

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

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

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

hive-solr 连接器 spark-solr 连接器

PS:

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

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

于 2016-09-13T17:04:58.043 回答
1

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

于 2012-02-25T23:50:17.020 回答
-1

参考指南 ConcurrentUpdateSolrServer可以/应该用于批量更新。

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

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

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

于 2014-03-31T18:58:51.000 回答