How to Import Structured Data into Solr
原文作者:Mikhail Khludnev
原文地址:https://dzone.com/articles/how-to-import-structured-data-into-solr
译者微博:@从流域到海域
译者博客:blog.csdn.net/solo95
如何将结构化数据导入Solr
这篇文章总结了我们在搜索中数据提取方面的经验。几乎所有的搜索项目都将现有数据注入到搜索引擎。在这篇文章中,我们主要关注的是旧的良好关系数据库作为数据源。我甚至不犹豫要键入什么:SQL数据库,还是not-NoSQL DB ?. 不用说,大多数这些考虑因素也适用于任何其他数据源,如文件,Web服务,NoSQL DB和分布式文件系统。
Solr数据导入处理器 - DIH
首先我要说明的是,我是数据导入处理器(Data Import Handler)的忠实粉丝。它与任何其他ETL工具一样方便- 您无需编写调用SolrJ的Java代码并在IDE中调试SQL查询结果。如果使用DIH,您可以只使用配置和复制粘贴式查询就能够在SolrAdmin中把玩查询和数据。因此,DIH非常适合快速原型搭建,但在生产环境中运行它怎会怎样?这里有几个问题(你也可以添加上你自己的问题):
- 缺乏并发性 - 单线程处理保持硬件处于空闲状态并需要大量时间才能完成;
- 缺乏高性能连接(更长远的看)。
我们将在下面检查这些点,但是,我们有证据表明DIH可用于真正巨大的部署。所以,尽管有这些限制,许多人仍在生产环境中运行DIH。为了解决并发问题,我们可以在逻辑上使用特制的查询将数据分片,并且平行的启动每个分片导入(线程)。连接性能问题可以通过持久性缓存(persistent caches)来解决,这可能会使连接操作更快,但我对这种方法持怀疑态度。现在让我们看看一些实的际问题。
通过DIH对块进行索引
我们作为Block连接支持者(Block Join proponents)而被熟知,因此,我们想要在DIH中队块进行索引。这是在5.1中已经实现了的,并且通过在子实体(第二级和更高级)中指定child =“true”就可以启用。
DIH中的嵌套实体(数据连接)
现在,让我们回到连接DIH中的实体。正如在上面提到的SOLR-2382中所完全描述的那样:“在子实体中使用SqlEntityProcessor可能导致”n 1选择“问题”,这个术语让我回想起以前在IT中面临的挑战,因此无法它在一段合理的时间(即能令人接受的短时间)内处理大量的数据,你可能会问为什么不要求RDBMS加入实体并在DIH中加入结果集。那么,如果两个表都驻留在同一个DB中,你就应该能想起笛卡尔的产品问题(cartesian product problem),如果你加入了两个或更多的子实体,就会发生这种情况,在这种情况下推荐的方法是使用hashmap在堆上去缓存关系的一边,当超过堆(我唯一关心的情况)时,建议将数据从堆中拿出放入BDB文件中.
在DIH中合并连接
事实证明,ETL社区意识到了这个问题,并已经有了已经用了几年的解决方案 - 外部合并连接(external merge join)。例如,在幼稚的N 1子查询之间增加的成千上万条记录的连接是从从几小时到加速到几分钟的方法。值得一提的是,我们也看到了相同的算法 - 在搜索引擎的实现中一次又一次地合并排序的序列(sequences)。这里是一个好消息:从5.0开始,合并连接可用于DIH中的任何EntityProcessor,方法是在子实体中指定join =“zipper”。当然你需要对两个输入进行排序,幸好这是由RDBMS的索引完成的。有趣的是,每当合并连接配置被修改时,看看Kettle ETL如何提醒这点。DIH不会使用这种弹出窗口打扰到您,但是如果入站流没有排序,则会引发异常。
你也可以处理多对多的关系,但是它需要在RDBMS中进行连接和排序,这通常没什么问题。现在是讨论线程和并发处理的时候了。在此之前,请记下合并连接算法不容易并行化,因此“散列连接”(在缓存数据中查找)更适合多线程处理。
多线程
DIH中没有线程。原文如此(前句可能是作者从官方文档中引用的)。我们在使用序列化处理时会有生产者 - 消费者的一般陷阱 -即每个人都在等待其相对的一方:
| 我们在DIH中有什么 | 我们想要什么 |
请注意,如果将DIH与SolrCloud一起运行,则会出现同样的问题,在这种情况下,DIH会同步向Solr提供一个文档,并在通过DistributingUpdateProcessor将每个文档发送到碎片引导程序之前阻止任何文档。
好的,关于问题已经谈的够多了,下面我们来谈谈其中的机会。我们可以并行化出站流(消费者):
- 如果DIH通过ConcurrentUpdateSolrClient或CloudSolrClient发送更新,它将从消费者中取消阻止生产者,从而有机会充分利用Solr机器进行索引。然而,目前的DIH设计下这是不可能的,但我们扔有很大的突破性尝试 - SOLR-7188。打起精神!这将是一个伟大的胜利,让我们运行DIH来作为一个真正的ETL工具。
- 还有另一个补丁在UpdateRequestProcessors图层上添加了线程- SOLR-3585,您可以将其视为服务器端的ConcurrentUpdateSolrClient。尽管我们从生产使用中得到了积极的反馈,但自从它做出一些贡献以来,我改变了主意,并没有将其视为在体系结构上很明智的方法。我想"提供适当级别的并发负载"和"压制"是客户端(即ETL)的职责。不过,如果您遇到一些麻烦的时候,则也可以使用它,例如,如果您有一些旧的脚本将会文件发布到Solr http终端中。
我们也可以考虑如何在后台线程中预取JdbcDataSource中的数据,以避免阻塞生产者。我绝对在某个地方存有这样的补丁,如果你需要可以联系我。
另一个ETL工具:Kettle
我也玩过几个开源的ETL工具,我选择Kettle作为例子。它内置了许多有用的工具,您绝对可以将其用作数据提取的工具箱。然而,我们热衷的是关于构建Solr XML的特定问题。我遇到的困难是平面关系元组(即二位元组,译者注)的限制(称之为行或记录)。然而,我们需要的是像这里的至少有三层嵌套的-父-子-属性(parent-child-attributes)。其中一种可能的解决方法是使用XML DOM作为数据结构,但不能在转换步骤之间按原样进行转换,并且需要将其转换为字符串,把一系列数据连接起来并再次分片,就像我们在这里一样。
我发现XML Join不具备良好的可扩展性,它的工作方式与内存中的XPath数据库很相似,这很好,但不是我所需要的。可能的解决方案之一是将DOM XML作为Kettle中的第一类数据类型引入,并让一些步骤按原样进行处理。
请继续关注,我们很快就会展示这出样一个概念验证。不要犹豫,分享你的愿景,经验和发现。这也是我在谈论ETL时使用的一个平台。
lucene/solr大数据lucene/solr大数据