360网站咋做学院网络营销策划方案
- 作者: 五速梦信息网
- 时间: 2026年03月17日 17:20
当前位置: 首页 > news >正文
360网站咋做,学院网络营销策划方案,机械厂做的网站模板叫什么,网站建设定制公众号小程序文章目录 概要一、Es数据存储1.1、_source1.2、stored fields 二、Doc values2.1、FieldCache2.2、DocValues 三、Fielddata四、Index sorting五、小结六、参考 概要 倒排索引 优势在于快速的查找到包含特定关键词的所有文档#xff0c;但是排序#xff0c;过滤、聚合等操作… 文章目录 概要一、Es数据存储1.1、_source1.2、stored fields 二、Doc values2.1、FieldCache2.2、DocValues 三、Fielddata四、Index sorting五、小结六、参考 概要 倒排索引 优势在于快速的查找到包含特定关键词的所有文档但是排序过滤、聚合等操作并不是倒排索引所擅长的。 假设文档有两个字段一个被分词的字段name,一个日期date。现在要查出包含花朵的所有文档中的按日期正序的前10个如果仅仅有倒排索引该如何实现的呢 答在name字段的倒排索引上找到包含关键词花朵的所有文档ID,然后获取date排序字段的值根据date值实时排序取前10个。 这种办法数据量少的时候还可以如果索引有百万级以上的数据就很低效了。显然MySQL、MongoDB等数据库按字段建立索引进行预排序更高效。 可以看到只有倒排索引的话排序是非常耗时的。Es维护组投入了大量时间和精力来优化排序查询随着版本更新在Es6基本完善了这一块工作分三部分 DocvaluesFielddataindex sorting Es对搜索与排序的区别解释很到位 Search needs to answer the question “Which documents contain this term?”, while sorting and aggregations need to answer a different question: “What is the value of this field for this document?”. 一、Es数据存储 Es是基于Lucene引擎的在Lucene中索引文档时原始字段信息经过分词、转换处理后形成倒排索引而原始内容本身并不直接保留。因此Lucene为了检索时能够获取到字段的原始值而设计了stored fields。另外Es自己追了一个_source字段保存了用户插入文档的字段值。 1.1、_source Es将文档内容以json形式存储在一个叫_source的字段中其默认是开启的。在Lucene层面_source仅仅是一个普通字段当开启时我们插入一个文档Es会自动把文档内容序列化赋值给_source字段组成新的文档结构再交由Lucene处理大致流程如下 可以看到在Lucene层面_source字段和其他字段并无特别之处。我们一般按如下方式调整_source字段 PUT my-index {mappings: {_source: {enabled: true, #是否开启_source字段默认开启includes: [ #开启_source字段是包含哪些字段支持正则.count,meta.],excludes: [ #开启_source字段是排除哪些字段支持正则meta.description,meta.other.*]}} }PS一般情况下我们都是开启_source字段的因为关闭_source后update、update_by_query、reindex等API将无法正常使用。 1.2、stored fields stored fields是Lucene引擎自带的特性在Es层面可通过store属性来控制默认不开启。 PUT my-index {mappings: {properties: {name: { type: text #默认关闭name字段的stored field},age: { type: long,store: true #开启age字段的stored field}}} }那么如果即开启_source字段某个字段的stored fields也开启那么这个字段值会被存储两次所以字段stored fields属性一般不开启如果开启最好通过_source的excludes属性排除该字段即可。 演示如下 [roottest ~]# curl -XPUT http://127.0.0.1:9200/test -H Content-Type: application/json -d {mappings:{properties:{status_code:{type:text},session_id:{type:keyword,store:true}}}} {acknowledged:true,shards_acknowledged:true,index:test} [roottest ~]# curl -XGET http://127.0.0.1:9200/test/_doc/1?pretty {_index : test,_id : 1,_version : 1,_seq_no : 0,_primary_term : 1,found : true,_source : {status_code : xxx bob,session_id : 999} } [roottest ~]# curl -XGET http://127.0.0.1:9200/test/_doc/1?prettystored_fieldsstatus_code {_index : test,_id : 1,_version : 1,_seq_no : 0,_primary_term : 1,found : true } [roottest ~]# curl -XGET http://127.0.0.1:9200/test/_doc/1?prettystored_fieldsstatus_code,session_id {_index : test,_id : 1,_version : 1,_seq_no : 0,_primary_term : 1,found : true,fields : {session_id : [999]} } Lucene的stored fields属于正排索引由于字段值经过分词转换为倒排索引后原始值并未保存为了根据doc id快速获取字段原始值而设计的。在Lucene下的应用场景是当需要返回原始字段值时就需要对对应字段设置stored fields; 在Es下由于设计了_source字段一般不需开启根据实际场景二者结合使用即可。 值得注意的是如果 _source 为不开启并且字段 store 属性也为 false 字段值就无法返回了但是如果字段index属性为true的话还是可以通过该字段查询文档的如果字段index属性为false的话该字段既不能查询也不会被返回是无效字段。 二、Doc values 默认情况下大多数字段都会被建立倒排索引这使得它们可以进行搜索。但是排序、聚合和脚本操作中的字段值需要获取文档某个字段的具体值。Doc values就是专为这种场景而诞生的简单来说就是实现根据doc id快速获取doc中某个字段值的目标。 doc values是列式存储主要包含doc id和字段具体值可能被压缩属于正排索引。Es默认每个字段的 doc values 都是开启的(不支持text 和 annotated_text类型字段)。 Doc values是Lucene引擎自带的特性从Lucene V4.0开始引入的在4.0之前都是依赖fieldCache机制用于缓存字段值。 2.1、FieldCache FieldCache,即字段缓存作用是加载所有文档中某个特定字段的值到内存便于随机获取某些文档中该字段的值。在FieldCache出现之前当用户需要访问各文档中某个字段的值时IndexSearcher.doc(docId)获得Document的所有字段值但访问速度比较慢而且只能获得被stored字段的值。 于是Lucene 在 3.0 提出了字段缓存FieldCache的概念这个 API 主要是在内部使用但开发者也可以外部调用在自定义排序或者自定义评分的时候都涉及到相关的接口。准确的说就是将相关的字段的值加载到内存中形成一维数组。加载字段缓存并不要求相关字段的值必须在索引中被stored而是要求必须 index并且不能分词实际上字段缓存的值是从倒排索引中转换而来。 FieldCache主要用于以下场景 加速对特定字段值的访问支持脚本中对字段值进行操作用于排序、聚合等操作。 具体原理见下图 但是这种方式有很大的不足 内存消耗大常驻内存大小是文档个数 * 字段类型大小性能开销大初始加载过程耗时需要遍历倒排索引及类型转换。可能导致其他请求延迟内存管理复杂内存管理不够灵活可能导致频繁的GC及性能问题。 Lucene 自 4.0 起提出了一个新的概念 DocValues, 允许用户在建索引的时候将相关字段的doc id 和字段值 之间的映射直接保存在索引文件中磁盘。因此在 lucene4.0 中Lucene 在根据doc id查询字段值时首先会根据doc id 去对应DocValues中获取字段的值。如果 DocValues 中不存在才会从倒排索引中进行类型转换再加载到内存中即FieldCache机制。也就是说默认会使用 DocValues代替FieldCache机制。 PS:事实上查了下在 lucene5 的 API 中FieldCache 已经被取消了,大家了解曾经有这么个机制即可 可以看到Lucene 5就没有了。 2.2、DocValues DocValues相比FieldCache机制大大节约内存获取字段值快其大概结构如下 | doc id |field value | | 1 | 500 | | 2 | 900 | | 3 | 1500 | | 4 | 100 | 使用方式 PUT my-index {mappings: {properties: {status_code: { type: keyword #默认开启status_code字段的doc value},session_id: { type: long,doc_values: false #关闭session_id字段的doc value}}} }生成时机 doc values 在文档被插入的时候与倒排索引同期生成即Es 为了提高查询排序速度插入文档时同时把字段的值加入倒排索引中也会把字段的值加入到doc values中空间换时间。存储位置磁盘使用时会被加载到内存。 通过下面案例可以清晰看到text 和 annotated_text类型的字段不支持doc_vlues属性。 [roottest ~]# curl -XPUT http://127.0.0.1:9200/test -H Content-Type: application/json -d {mappings:{properties:{status_code:{type:text,doc_vlues:true},session_id:{type:keyword,doc_values:false}}}} {error:{root_cause:[{type:mapper_parsing_exception,reason:unknown parameter [doc_vlues] on mapper [status_code] of type [text]}]}} Es 中text 和 annotated_text类型的字段不支持doc_vlues属性主要是因为Lucene中Docvalues机制保存的是字段原始值并不支持分词后的结果 为了更好地理解Es如何使用Lucene的DocValues机制我们可以看一下相关API; public class LuceneExample {public static void main(String[] args) throws Exception {// 创建一个内存目录来存储索引Directory directory new RAMdirectory();// 使用标准分析器StandardAnalyzer analyzer new StandardAnalyzer();// 配置IndexWriterIndexWriterConfig config new IndexWritereConfig(analyzer);// 创建IndexWriterIndexWriter iwriter new IndexWriter(directory, config);// 创建文档并添加字段Document doc new Document();doc.add(new StringField(id, 1, Field.Store.YES));//字段id被建立倒排索引并存储其原始值并且不会被分词doc.add(new TextField(title, Lucene, Field.Store.YES));//字段title被建立倒排索引并存储其原始值但会被分词doc.add(new TextField(content, Hello Lucene,My is…, Field.Store.NO));//字段content被建立倒排索引但不存储其原始值且会被分词doc.add(new LongField(createTime, 1672564789001L));//对字段createTime建立倒排索引doc.add(new StoredField(createTime, 1672564789001L));//存储字段createTime原始值doc.add(new StoredField(name, Bob));//只存储字段name原始值doc.add(new NumericDocValuesField(name, 1672564789001L));//对字段createTime建立docvaluesdoc.add(new SortedNumericDocValuesField(list, 3));//对字段list建立docvaluesdoc.add(new SortedNumericDocValuesField(list, 9));//对字段list建立docvalues// 将文档写入索引iwriter.addDocument(doc);// 关闭写入器iwriter.close();} }通过这个案例就可以想到我们就文档提交给Es后Es也是这样调用Lucene的API来完成工作。Es会根据mapping中字段配置来组装doc: 案例中name和createTime字段的mapping配置如下: {name: {type: textindex: false,store: true,doc_values: false},age: {type: long,index: true,store: true,doc_values: true} }Es在调用Lucene的API时除了我们提交的字段Es还会预留的系统字段用作一些特殊的目的这些字段对于Lucene来说与用户自定义的Field无任何区别只不过Es根据这些系统字段不同的使用目的定制有不同的索引方式,比如_uid、_source字段等_uid字段就设置成会被索引不需要分词不需要被Store不需要Docvalues。 看到这里就有些同学会问题Lucene除了建立倒排索引还有Store,Docvalues三者都会存储字段值如果都设置了一个字段值岂不是被存了三份 说来确实是这样三者各自有不同的作用倒排索引用于快速定位哪些文档包含搜索关键词Store是为了查询时返回文档中字段原始值Docvalues是为了查询时便于进行排序、聚合等操作。 因为Store是正排行式存储便于一次获取文档中所有字段的值单行多列Docvalues是正排列式存储便于快速获取单个字段多个值单列多行。 在实际业务中根据业务需求和性能要求灵活选择设置这些属性即可。 三、Fielddata Fielddata是Es自身的特性与Lucene无关Es之所以会维护Fielddata就是因为Lucene的Docvalues不支持text 和 annotated_text类型的字段本质是Docvalues只存储字段原始值不支持存储字段值分词后的结果。 Fielddata是Es用来对text 和 annotated_text类型的字段进行排序、聚合、脚本计算等操作的机制。默认关闭此时无法对该类型字段进行排序等操作。 PUT my-index-000001/_mapping {properties: {name: { type: text,fielddata: true, #字段name开启Fielddata特性fielddata_frequency_filter: {min: 0.001,max: 0.1,min_segment_size: 500}}} }只有text和annotated_text类型字段支持Fielddata特性。 生成时机使用时动态生成懒加载存储位置JVM内存不占用磁盘空间 看到这里有同学会觉得Es的Fielddata和Lucene的FieldCache很相似,没错很像但 Es的Fielddata只支持text和annotated_text类型字段Lucene的FieldCache支持所有Es的Fielddata使用了更紧凑的内存表示内存消耗更小Es的Fielddata通过优化的数据结构提高排序、聚合等操作Es的Fielddata提供更灵活的内存管理方式如用户通过fielddata_frequency_filter参数过滤掉低频词汇节约内存。 Es通过Fielddata和Docvallues实现对所有字段排序、聚合等操作的支持。 Fielddata预加载 四、Index sorting Index sorting属于Lucene特性。 Lucene 早期曾引入了一个离线的排序工具——IndexSorter。IndexSorter 把需要排序的索引完全复制了一份将新的复制索引中的文档按用户指定的顺序重新排序。因为排序后的索引是一个新的索引每次源索引中有新的数据更新不得不重新执行一遍这个工具。IndexSorter 工具是第一次在索引写入阶段而不是查询阶段对文档进行排序的尝试。 针对索引预排序社区提出了一个新的概念“early termination”。假设你要遍历出前N个文档并且文档是按 date 字段排序的。如果索引存储在磁盘上时已经是有序的了那么我们遍历出前N个文档就可以直接返回而不需要遍历所有的文档。这就是我们所说的“early termination”。提早的返回查询结果可以明显的缩短查询响应时间特别是含有排序的查询。刚才介绍的离线排序的方案不能满足有大量文档更新的场景这也是为什么最终离线排序方案会被其他方案取代。 Es排序定义如下 单Field排序定义 PUT events {settings : {index : { #按timestamp倒序sort.field : timestamp,sort.order : desc }},mappings: {properties: {timestamp: {type: date}}} }多字段排序定义 PUT events {settings : {index : {sort.field : [timestamp,age],sort.order : [desc,desc] }},mappings: {properties: {timestamp: {type: date},age:{type: integer}}} }Es Settings支持 Index Sorting 4个配置 index.sort.field对应排序的Field可指定一个或者多个Field优先按第一个排序相同的情况下在按后续的Field排序index.sort.order对应Field的排序规则只能时asc或者时descindex.sort.mode当对应的Field是数组时取Max或者Min的值作为排序的基准;index.sort.missing当对应的Field为null时排第一个还是最后一个。 索引排序是一个很不错的解决方案但是只能以单一方式进行索引排序。索引排序并不适用于具有下列特征的排序查询 采用不同的排序标准例如索引定义的是降序你查询用的是升序所用排序字段组合不同于索引排序定义中指定的组合。 我们这里也看看Lucene中的API: IndexWriterConfig config new IndexWritereConfig(analyzer); SortField sf1 new SortField(createTime,SortField.Type.LONG) Sort sorts new Sort(new SortField[]{sf1}) //支持多个字段 config.setIndexSort(sorts); //设置索引排序定义可以看到Es就是根据用户的settings.index配置进而转换成调用Lucene的这些API来完成工作的。 由于索引排序是在索引生成阶段完成的根据测试不可避免的降低了写入性能此功能最多可将写入速度降低 40-50%。由于排序是一个很耗时的操作所以如果您最关注的是索引速度则必须谨慎考虑是否要开启索引排序功能。 Lucene针对索引排序做了很多优化在新segment生成后刷盘时对段内所有文档进行一次排序在segment merge时对所有段的文档进行排序此时segment内文档有序相当于合并有序数组 O(N)。 五、小结 通过前几章节的描述可知Es排序是一个复杂的场景在优化过程中不断地打补丁不像MySQLMongoDB依赖Btree实现。主要分为 实时排序text类型字段依赖Fielddata机制其他类型字段依赖Docvalues机制预排序在创建索引时定义排序规则一个索引只能定义一个限制较大。 六、参考 1]Es官网_source字段 2]Es官网store属性 3]Es官网doc_values属性 4]Lucene官网FIELD对像 5]Es Fielddata知识点梳理 6]Es 优化排序查询 7]Es 索引排序为人不知的优势-减少索引磁盘占用 8]Es 索引预排序分析和英文版 9]Lucene Fieldcache机制原理 10]Lucene源码解析——DocValue存储方式 11]Lucene 段合并原理
- 上一篇: 360网站图标怎么做的新淘客wordpress
- 下一篇: 360网站在系统那里微信营销软件商城
相关文章
-
360网站图标怎么做的新淘客wordpress
360网站图标怎么做的新淘客wordpress
- 技术栈
- 2026年03月17日
-
360网站免费推广怎么做ueditor wordpress4.5
360网站免费推广怎么做ueditor wordpress4.5
- 技术栈
- 2026年03月17日
-
360网站挂马检测网络服务有点问题别紧张试试看刷新页面
360网站挂马检测网络服务有点问题别紧张试试看刷新页面
- 技术栈
- 2026年03月17日
-
360网站在系统那里微信营销软件商城
360网站在系统那里微信营销软件商城
- 技术栈
- 2026年03月17日
-
360网站怎么做ppt3g手机网站建设
360网站怎么做ppt3g手机网站建设
- 技术栈
- 2026年03月17日
-
360站长工具thinkphp5菜鸟教程
360站长工具thinkphp5菜鸟教程
- 技术栈
- 2026年03月17日






