Es 索引查询排序分析

news2024/11/24 18:32:09

文章目录

    • 概要
    • 一、Es数据存储
        • 1.1、_source
        • 1.2、stored fields
    • 二、Doc values
        • 2.1、FieldCache
        • 2.2、DocValues
    • 三、Fielddata
    • 四、Index sorting
    • 五、小结
    • 六、参考

概要

倒排索引 优势在于快速的查找到包含特定关键词的所有文档,但是排序,过滤、聚合等操作并不是倒排索引所擅长的。

假设文档有两个字段,一个被分词的字段name,一个日期date。现在要查出包含花朵的所有文档中的按日期正序的前10个,如果仅仅有倒排索引该如何实现的呢?
答:在name字段的倒排索引上找到包含关键词花朵的所有文档ID,然后获取date排序字段的值,根据date值实时排序,取前10个。
这种办法数据量少的时候还可以,如果索引有百万级以上的数据,就很低效了。显然,MySQL、MongoDB等数据库按字段建立索引进行预排序更高效。

可以看到只有倒排索引的话,排序是非常耗时的。Es维护组投入了大量时间和精力来优化排序查询,随着版本更新,在Es6基本完善了这一块工作,分三部分:

  1. Docvalues
  2. Fielddata
  3. index 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处理,大致流程如下:

Es _source写入过程
可以看到,在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属性排除该字段即可。

演示如下:

[root@test ~]# 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"}
[root@test ~]# 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"
  }
}
[root@test ~]# curl -XGET http://127.0.0.1:9200/test/_doc/1?pretty\&stored_fields=status_code
{
  "_index" : "test",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true
}
[root@test ~]# curl -XGET http://127.0.0.1:9200/test/_doc/1?pretty\&stored_fields=status_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 都是开启的(不支持textannotated_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主要用于以下场景:

  • 加速对特定字段值的访问;
  • 支持脚本中对字段值进行操作;
  • 用于排序、聚合等操作。

具体原理见下图:
Lucene 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 4可以看到,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中(空间换时间)。
  • 存储位置:磁盘,使用时会被加载到内存。

通过下面案例可以清晰看到textannotated_text类型的字段不支持doc_vlues属性

[root@test ~]# 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 中textannotated_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();
        // 配置IndexWriter
        IndexWriterConfig config = new IndexWritereConfig(analyzer);
        // 创建IndexWriter
        IndexWriter 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建立docvalues
        doc.add(new SortedNumericDocValuesField("list", 3));//对字段list建立docvalues
        doc.add(new SortedNumericDocValuesField("list", 9));//对字段list建立docvalues
        // 将文档写入索引
        iwriter.addDocument(doc);
        // 关闭写入器
        iwriter.close();
    }
}

通过这个案例就可以想到我们就文档提交给Es后,Es也是这样调用Lucene的API来完成工作。Es会根据mapping中字段配置来组装doc:
案例中name和createTime字段的mapping配置如下:

{
	"name": {
		"type": "text""index": 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不支持textannotated_text类型的字段,本质是Docvalues只存储字段原始值,不支持存储字段值分词后的结果。

Fielddata是Es用来对textannotated_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很相似,没错,很像,但:

  1. Es的Fielddata只支持text和annotated_text类型字段,Lucene的FieldCache支持所有;
  2. Es的Fielddata使用了更紧凑的内存表示,内存消耗更小;
  3. Es的Fielddata通过优化的数据结构,提高排序、聚合等操作;
  4. 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个配置:

  1. index.sort.field:对应排序的Field,可指定一个或者多个Field,优先按第一个排序,相同的情况下在按后续的Field排序;
  2. index.sort.order:对应Field的排序规则,只能时asc或者时desc;
  3. index.sort.mode:当对应的Field是数组时,取Max或者Min的值作为排序的基准;
  4. 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%。由于排序是一个很耗时的操作,所以如果您最关注的是索引速度,则必须谨慎考虑是否要开启索引排序功能。
Es Index sort benchmark

Lucene针对索引排序做了很多优化,在新segment生成后刷盘时对段内所有文档进行一次排序,在segment merge时对所有段的文档进行排序(此时segment内文档有序,相当于合并有序数组 O(N))。

五、小结

通过前几章节的描述可知,Es排序是一个复杂的场景,在优化过程中不断地打补丁,不像MySQL,MongoDB依赖B+tree实现。主要分为:

  1. 实时排序:text类型字段依赖Fielddata机制,其他类型字段依赖Docvalues机制;
  2. 预排序:在创建索引时定义排序规则,一个索引只能定义一个,限制较大。

六、参考

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 段合并原理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1828802.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

室内定位技术解析:蓝牙信标在室内导航中的应用

室内定位技术,作为现代导航领域的重要突破,解决了GPS在室内空间定位的局限,为我们提供了一种全新的空间认知和利用方式。本文将以蓝牙技术为例,深入解析室内定位的工作原理、关键技术和系统构成,以及在现代导航中的应用…

库的制作 与 使用 (Linux下)

目录 动静态库的制作 前置知识 库的基本构造 问题 分析 要给什么文件 如何更好的让别人使用 库的生成 静态库的生成 makefile参考 动态库的生成 makefile参考(包含动态库和静态库生成) 库的使用 法一:放入系统路径 弊端 法二…

【MATLAB】语法

MATLAB 基本语法(%{和%}) 赋值 函数名值&#xff1b;for for i1:10循环语句 end//while x0; sum0; while x<100sumsumx;x; end//if if x > 1f x^2 1; elsef 2 * x endswitch onum input(请输入一个数); switch num case -1 //注意case后面没有冒号disp(I am…

[Linux] TCP协议介绍(3): TCP协议的“四次挥手“过程、状态分析...

TCP协议是面向连接的 上一篇文章简单分析了TCP通信非常重要的建立连接的"三次握手"的过程 本篇文章来分析TCP通信中同样非常重要的断开连接的"四次挥手"的过程 TCP的"四次挥手" TCP协议建立连接 需要"三次握手". "三次挥手&q…

英伟达开源最强通用模型Nemotron-4 340B

英伟达的通用大模型 Nemotron&#xff0c;开源了最新的 3400 亿参数版本。 本周五&#xff0c;英伟达宣布推出 Nemotron-4 340B。它包含一系列开放模型&#xff0c;开发人员可以使用这些模型生成合成数据&#xff0c;用于训练大语言模型&#xff08;LLM&#xff09;&#xff0…

【CICID】GitHub-Actions语法

[TOC] 【CICID】GitHub-Actions语法 1 场景 ​ 当我们开发过程中&#xff0c;经常需要提交代码&#xff0c;打包&#xff0c;部署新代码到对应的环境&#xff0c;整个过程都是人工手动操作&#xff0c;占据开发人员大量时间&#xff0c;并且很繁琐容易出错。所以需要借助一些…

奥特曼谈AI的机遇、挑战与人类自我反思:中国将拥有独特的大语言模型

奥特曼在对话中特别提到&#xff0c;中国将在这个领域扮演重要角色&#xff0c;孕育出具有本土特色的大语言模型。这一预见不仅彰显了中国在全球人工智能领域中日益增长的影响力&#xff0c;也预示着未来技术发展的多元化趋势。 ①奥特曼认为AI在提升生产力方面已显现积极作用&…

蔡崇信“预言”:微软与OpenAI未来极有可能会分道扬镳

近日&#xff0c;在美国投行摩根大通于上海举行的第二十届全球中国峰会上&#xff0c;阿里巴巴集团联合创始人、董事局主席蔡崇信与摩根大通北亚区董事长兼大中华区投资银行业务副主席关金星&#xff08;Kam Shing Kwang&#xff09;进行了一场精彩对话。蔡崇信深入分享了他对公…

【LVGL】Guider 界面分析

文章目录 前言架构创建 UI切换界面空间释放分析创建页面空间变化 前言 分析Gui Guider-1.7.2-GA 生成的 LVGL 界面切换&#xff0c;资源管理等处理 架构 所有控件存放于同一个结构体 lv_ui 内&#xff0c;每个页面都至少包含 screen_xxx 和 screen_xxx_del 两个成员 typede…

C语言:文件系统

一、目录和文件 在当前目录下使用touch 创建一个名为 -a的文件: touch -a ; // 错误&#xff0c; touch -- -a//正确 touch ./-a 正确 ls -n可以看到对象的用户id&#xff0c;可以在/etc/passwd中查看&#xff0c;/etc/group可以看到组号 获取文件属性 #include <sys/ty…

苹果加大AI布局,上海新店开业昭示中国市场新动向

随着全球科技巨头纷纷进军人工智能领域&#xff0c;苹果公司亦不甘示弱&#xff0c;近期在上海静安新店的开业以及CEO蒂姆库克的一系列动作&#xff0c;都显示出苹果在AI方面的雄心壮志。这不仅是对未来技术趋势的积极回应&#xff0c;更是对市场竞争态势的精准把握。 库克的访…

Gone框架介绍26 - Gone v1.x 版本 正式发布,更加强大的依赖注入,更加卓越的执行效率

gone是可以高效开发Web服务的Golang依赖注入框架 github地址&#xff1a;https://github.com/gone-io/gone 文档地址&#xff1a;https://goner.fun/zh/ 文章目录 优化和新特性gone 核心功能增强内置Goners覆盖测试 后续计划 优化和新特性 gone 核心功能增强 重构了函数参数依…

Qt项目天气预报(1) - ui界面搭建

ui中部 效果演示 ui效果 显示效果 控件列表 配合右图查看 居中对齐-label 设置label居中对齐(别傻傻的空格对齐了) 间距配置 widget03 外围的widget对象: 包含label 和 widget0301&#xff0c;如下图 widget0301 内围的widget对象&#xff0c;如下图 样式表 widget03 …

Java与数据库连接技术JDBC关键核心之PreparedStatement以及SQL注入演示解决和原理

PreparedStatement SQL注入 执行预编译的SQL对象 这样也能登录成功 模拟 SQL注入是这个原因 现在基本上不存在SQL注入的问题 解决 SQL注入就是传一些语句导致原来的SQL语句改变了 修改代码 通过设置参数的方式 就能防止SQL注入 实际上我们进行了一个转化 将字符和关键字进…

【归并排序】| 详解归并排序核心代码之合并两个有序数组 力扣88

&#x1f397;️ 主页&#xff1a;小夜时雨 &#x1f397;️专栏&#xff1a;动态规划 &#x1f397;️如何活着&#xff0c;是我找寻的方向 目录 1. 题目解析2. 代码 1. 题目解析 题目链接: https://leetcode.cn/problems/merge-sorted-array/description/ 本道题是归并排序的…

Python学习打卡:day07

day7 笔记来源于&#xff1a;黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了 目录 day753、列表的常用操作课后练习题54、列表的循环遍历列表的遍历—— while 循环列表的遍历—— for 循环while 循环和 for 循环的对比练习 55、元组…

回归预测 | Matlab实现NGO-HKELM北方苍鹰算法优化混合核极限学习机多变量回归预测

回归预测 | Matlab实现NGO-HKELM北方苍鹰算法优化混合核极限学习机多变量回归预测 目录 回归预测 | Matlab实现NGO-HKELM北方苍鹰算法优化混合核极限学习机多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现NGO-HKELM北方苍鹰算法优化混合核极限…

Kotlin 协程真的轻量吗?

前言 在官方文档的介绍中,提到了: 协程是轻量的 并给出了一个例子: fun main() = runBlocking {repeat(50_000) {// 启动大量的协程launch {delay

模型算法—线性回归

线性回归是统计学中最常见的一种回归分析方法&#xff0c;用于建立自变量&#xff08;解释变量&#xff09;和因变量&#xff08;响应变量&#xff09;之间的线性关系。线性回归模型可以用来预测一个或多个自变量对应的因变量的值。 线性回归的基本形式如下&#xff1a; &…

【麒麟虚拟机】NetworkManager没有运行

麒麟V10 建linux麒麟虚拟机&#xff0c;发现&#xff0c;网络没有配置 提示&#xff0c;NetworkManager没有运行。编辑联接也不能配置 解决方法&#xff0c;在终端输入命令&#xff1a; sudo systemctl start NetworkManager 启动以后&#xff0c;编辑连接选自动以太网&…