SOLR—从csv文件导入2000万个文档的最佳方法
我目前的任务是找出在solr中加载数百万文档的最佳方法。 数据文件是以csv格式从数据库导出的 目前,我正在考虑将文件拆分为较小的文件,并在使用curl发布较小的文件时使用脚本 我注意到,如果发布大量数据,大多数情况下请求都会超时 我正在寻找数据导入器,它似乎是一个不错的选择 您还有其他想法吗SOLR—从csv文件导入2000万个文档的最佳方法,csv,import,solr,bulkinsert,dataimporthandler,Csv,Import,Solr,Bulkinsert,Dataimporthandler,我目前的任务是找出在solr中加载数百万文档的最佳方法。 数据文件是以csv格式从数据库导出的 目前,我正在考虑将文件拆分为较小的文件,并在使用curl发布较小的文件时使用脚本 我注意到,如果发布大量数据,大多数情况下请求都会超时 我正在寻找数据导入器,它似乎是一个不错的选择 您还有其他想法吗 谢谢一定要先把它们加载到一个普通的数据库中。有各种各样的工具来处理CSV(例如),所以应该很容易。使用也非常简单,因此这似乎是加载数据最无摩擦的方式。这种方法也会更快,因为您不会有不必要的网络/HTTP开
谢谢一定要先把它们加载到一个普通的数据库中。有各种各样的工具来处理CSV(例如),所以应该很容易。使用也非常简单,因此这似乎是加载数据最无摩擦的方式。这种方法也会更快,因为您不会有不必要的网络/HTTP开销。除非数据库已经是您的解决方案的一部分,否则我不会给您的解决方案增加额外的复杂性。引用是您的servlet容器发出会话超时 在我看来,您有两个选择(按照我的偏好顺序): 增加容器超时 增加容器超时时间。((“maxIdleTime”参数,如果您使用的是嵌入式Jetty实例) 我想你只是偶尔索引这么大的文件?临时增加超时可能只是最简单的选择 分割文件 下面是执行此任务的简单unix脚本(将文件拆分为500000行块): 解析文件并分块加载 下面的groovy脚本使用opencsv和solrj解析CSV文件,并每500000行将更改提交给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()
}
在Solr4.0(目前处于BETA版)中,可以使用UpdateHandler直接导入本地目录中的CSV。从中修改示例
这将从本地位置流式传输文件,因此无需将其分块并通过HTTP发布。ConcurrentUpdateSolrServer
可以/应该用于批量更新
Javadocs有些不正确(,):
ConcurrentUpdateSolrServer缓冲所有添加的文档并将它们写入打开的HTTP连接
它不会无限期地进行缓冲,但最多可达到
int queueSize
,这是一个构造函数参数。以上回答很好地解释了单机的摄取策略
如果您有大数据基础设施,并且希望实现分布式数据摄取管道,那么就没有更多的选择了
- 确保没有防火墙阻止客户端节点和solr/solrcloud节点之间的连接
- 为数据摄取选择正确的目录工厂,如果不需要近实时搜索,则使用
StandardDirectoryFactory
- 如果在摄取期间客户端日志中出现以下异常,请在
文件中调整solrconfig.xml
和autoCommit
配置autoSoftCommit
马克,谢谢你的详细回答。这和我想弄明白的是一致的。我将有巨大的负荷作为第一次和更新增量每小时左右。我想我知道第一批货的选择。但是,我不确定什么是最易于管理的更新过程。我正在寻找可配置的健壮更新过程。任何关于这方面的信息都将不胜感激。谢谢。我建议为新文件创建一个“输入”目录,并在索引后将文件移动到“已处理”目录中。简单易维护。。。。然而。。。。你说CSV文件来自数据库?在这种情况下,如果您可以访问数据库,那么您可能需要更好地使用DIH处理程序。文件将从数据库中取出。不确定加载它们的目的是什么?好的,然后使用数据导入处理程序直接读取它们。这个选项有什么问题吗?+1我做了一些快速性能测试,DIH的性能比批量提交好一个数量级。但这只是第一印象。当数据库位于与安装Solr的位置不同的网络位置时,DIH无法处理拉取大量数据。套接字连接超时随之发生。必须使用opencsv将数据从数据库拉入csv文件中,并将其分成小块。然后使用FileListenityProcessor和LineEntityProcessor对数据进行索引进入Solr。@Vijay这听起来更像是网络基础设施/DB配置的问题,而不是DIH或Solr的问题。UpdateHandler与DataImportHandler的性能如何?在这两种情况下,输入都是CSV。我没有运行任何基准测试,但DataImportHandler的性能非常好。我们做了大约2000万条记录,在大约一小时内得到了大约7GB的索引(经过优化)。此外,在将数据添加到索引之前,我们还必须对数据进行一些转换,因此无法使用UpdateHandler进行转换。谢谢!我也在做这个,它就像一个符咒。约50万条记录(大小为8gb),耗时约40分钟。
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()
}
curl http://localhost:8983/solr/update?stream.file=exampledocs/books.csv&stream.contentType=text/csv;charset=utf-8