
取决于你的设计
你可以建索引的时候,把所有字段都存进去,这样你搜索时,就可以取到,直接使用。如果你的 index 在内存或闪存的话,会比较快,不过要求空间比较大。而且有数据不一致的问题
另外,你也可以只存对应的 KEY,然后去数据库查。这样就是要查两遍
FieldTermVectorWITH_POSITIONS只表示额外索引这个索引项的当前位置信息
并没有存储数据 所以内容为null
如果需要检索内容必须用FieldStoreYES来存储数据信息
用Field(name, value, store, index)或者Field(name, value, store, index,termvector)
Select from table where (A like '%AAA%' and A like '%AAA%' and A like '%AAA%')
or (B like '%BBB%' and B like '%BBB%' and B like '%BBB%') or (C like '%CCC%' and C like '%CCC%' and C like '%CCC%')
本文中的数据平台已迭代三个版本,从头开始遇到很多常见的难题,终于有片段时间整理一些已完善的文档,在此分享以供所需朋友的。实现参考,少走些弯路,在此篇幅中偏重于ES的优化,目前生产已存储百亿数据,性能良好,关于HBase,Hadoop的设计优化估计有很多文章可以参考,不再赘述。
项目背景:在一业务系统中,部分表每天的数据量过亿,已按天分表,但业务上受限于按天查询,并且DB中只能保留3个月的数据(硬件高配),分库代价较高。
改进版本目标:
谈到优化必须能了解组件的基本原理,才容易找到瓶颈所在,以免走多种弯路,先从ES的基础结构说起(如下图):
一些基本概念:
ES依赖一个重要的组件Lucene,关于数据结构的优化通常来说是对Lucene的优化,它是集群的一个存储于检索工作单元,结构如下图:
在Lucene中,分为索引(录入)与检索(查询)两部分,索引部分包含 分词器、过滤器、字符映射器 等,检索部分包含 查询解析器 等。一个Lucene索引包含多个segments,一个segment包含多个文档,每个文档包含多个字段,每个字段经过分词后形成一个或多个term。
通过Luke工具查看ES的lucene文件如下,主要增加了_id 和 _source字段:
Lucene 索引文件结构主要的分为:词典、倒排表、正向文件、DocValues等,如下图:
Lucene 随机三次磁盘读取比较耗时。其中fdt文件保存数据值损耗空间大,tim和doc则需要SSD存储提高随机读写性能。
另外一个比较消耗性能的是打分流程,不需要则可屏蔽。
关于DocValues:
倒排索引解决从词快速检索到相应文档ID, 但如果需要对结果进行排序、分组、聚合等 *** 作的时候则需要根据文档ID快速找到对应的值。
通过倒排索引代价缺很高:需迭代索引里的每个词项并收集文档的列里面 token。这很慢而且难以扩展:随着词项和文档的数量增加,执行时间也会增加。Solr docs对此的解释如下:
在lucene 40版本前通过FieldCache,原理是通过按列逆转倒排表将(field value ->doc)映射变成(doc -> field value)映射,问题为逐步构建时间长并且消耗大量内存,容易造成OOM。
DocValues是一种列存储结构,能快速通过文档ID找到相关需要排序的字段。在ES中,默认开启所有(除了标记需analyzed的字符串字段)字段的doc values,如果不需要对此字段做任何排序等工作,则可关闭以减少资源消耗。
ES中一个索引由一个或多个lucene索引构成,一个lucene索引由一个或多个segment构成,其中segment是最小的检索域。
数据具体被存储到哪个分片上:shard = hash(routing) % number_of_primary_shards
默认情况下 routing参数是文档ID (murmurhash3),可通过 URL中的 _routing 参数指定数据分布在同一个分片中,index和search的时候都需要一致才能找到数据,如果能明确根据_routing进行数据分区,则可减少分片的检索工作,以提高性能。
在我们的案例中,查询字段都是固定的,不提供全文检索功能,这也是几十亿数据能秒级返回的一个大前提:
1、ES仅提供字段的检索,仅存储HBase的Rowkey不存储实际数据。
2、实际数据存储在HBase中,通过Rowkey查询,如下图。
3、提高索引与检索的性能建议,可参考官方文档(如 >
好像没有直接的方法,不过可以通过try catch的方法来判断,如: Boolean flag=false; try{ String contents=searcherdoc(docNum)get("content"); flag=true; } catch(Exception e){ flag=false; } 如果flag=ture说明content这个字段是存在的
TermQuery是按词条进行查询,就是查询的最小单位是Term(也就是一个字段名称),你看看这个链接,肯定对你有帮助:>
以上就是关于lucene 检索,是先把数据从数据库里查出来,在对查出来的数据。处理吗是这样吗全部的内容,包括:lucene 检索,是先把数据从数据库里查出来,在对查出来的数据。处理吗是这样吗、lucene 查询部分字段总是返回 null、lucene.net多字段查询问题等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)