首页 > 其他分享 >elasticSearch基本概念

elasticSearch基本概念

时间:2024-01-27 16:25:03浏览次数:30  
标签:节点 索引 文档 分片 elasticSearch 查询 基本概念 es

elasticSearch基本概念

基本概念

索引(index)

es将数据存储在一个或多个索引中。es在内部使用Lucene将数据写入索引或者从索引汇总检索数据。es中的索引可能由一个或多个Lucene索引构成。

文档(document)

文档是es世界中的主要实体。文档由字段构成,每个字段包含字段名以及一个或多个字段值。文档之间可能由各自不同的字段集合,文档并没有固定的模式或强制的结构。从客户端的角度看,文档是一个json对象。

类型(type)

通过类型允许用户在一个索引中存储多种文档类型,并为不同文档类型提供不同的映射。高版本中es的类型默认为_doc,且一个索引对应一个类型。

映射(mapping)

所有文档在写入索引前都要被分析,用户可以设置映射决定如何将输入的文本分割成词条,哪些词条应该被过滤掉,或者需要附加处理。es可以根据字段值自动检测字段类型,但是一般还是自定义映射。

节点(node)

单个es的服务实例称为节点。es一般以集群的形式出现,其包含了多个节点。

es节点可以分为3类:

  • 数据节点(data node):用来持有数据,提供对这些数据的搜索功能;
  • 主节点(master node):作为监督者负责控制其他节点的工作。一个集群只有一个主节点;
  • 部落节点(tribe node):部落节点用于连接多个集群,允许在多个集群上执行几乎所有可以在单集群es上执行的功能。

集群(cluster)

多个协同工作的es节点的集合称为集群。

分片(shard)

集群允许系统存储的数据总量超过单机容量。为了满足这个需求,es将数据散布到多个Lucene索引上去。这些Lucene索引称为分片(shard),一个shard就是一个Lucene索引,而散布这些分片的过程叫做分片处理(sharding)。es会自动完成分片处理,并且让用户看来这些分片更像是一个大索引。分片的数量是在索引创建时就配置好的,之后无法改变,除非创建一个新索引并重新索引全部数据

副本(replica)

分片处理允许用户推送超过单机容量的数据到es集群。副本则解决了访问压力过大时单机无法处理所有请求的问题。为每个分片创建冗余的副本,处理查询时可以将这些副本当做最初的主分片(primary shard)使用。如果主分片所在节点宕机,es会自动从该分片的副本中选出一个作为新的主分片。可以在任意时间点添加或移除副本


倒排索引(inverted index)

倒排索引包含两个部分:

  • 单词词典:记录所有文档单词,记录单词到倒排列表的关联关系;
  • 倒排列表:记录单词和对应文档集合,由倒排索引项构成。

倒排索引项:

  • 文档
  • 词频(TF):单词在文档中出现的次数,用于相关性评分;
  • 位置(position):单词在文档中分词的位置;
  • 偏移(offset):记录单词开始结束的位置,实现高亮显示。

数据的输入输出

es的数据操作的最小单位是文档。

索引文档

一个文档可以由_index_type_id唯一标识。

使用自定义id

PUT /{index}/{type}/{id}
{
  "field": "value",
  ...
}

自动生成id

POST /{index}/{type}/
{
  "field": "value",
  ...
}

自动生成的 ID 是 URL-safe、 基于 Base64 编码且长度为20个字符的 GUID 字符串。 这些 GUID 字符串由可修改的 FlakeID 模式生成,这种模式允许多个节点并行生成唯一 ID ,且互相之间的冲突概率几乎为零。

获取一个文档

GET /website/_doc/123?pretty

或者

curl -X GET "localhost:9200/website/_doc/123?pretty"

返回文档的部分域

使用_source

GET kibana_sample_data_flights/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "DestCountry": "AU"
          }
        },
        {
          "match": {
            "OriginCountry": "ES"
          }
        }
      ]
    }
  },
  "_source": {
    "includes": [
      "DistanceKilometers",
      "DestCountry",
      "OriginCountry"
    ]
  }
}

或者:

curl -X GET "localhost:9200/website/_doc/123?_source=title,text&pretty"

检查文档是否存在

HEAD /website/_doc/123

或者

curl -i -XHEAD http://localhost:9200/website/_doc/123

乐观并发控制

es是分布式的。当文档创建更新或者删除时,新版本的文档必须复制到集群中的其他节点。es是异步和并发的,意味着这些请求到达目的地的顺序也许是乱的,es采用了乐观锁的机制保证文档的旧版本不会覆盖新版本。

在旧版本es中,使用_version版本号来作为乐观锁控制。在新版es中,采用_seq_no_primary_term来控制。

PUT /colors/_doc/5?if_seq_no=11&if_primary_term=5
{
  "color": "brown"
}

若要在新版本中使用_version来控制,做法为:

PUT /colors/_doc/5?version=6&version_type=external
{
  "color": "brown"
}

_primary_term:_primary_term和_seq_no一样是一个整数,每当Primary Shard发生重新分配时,比如重启,Primary选举等,_primary_term会递增1。

取回多个文档

es可以将多个请求合并成一个,避免单独处理每个请求花费的网络延迟和开销。通过mget来获取多个文档。

GET /_mget
{
  "docs": [
    {
      "_index": "colors",
      "_id": 1
    },
    {
      "_index": "kibana_sample_data_flights",
      "_id": "5ZNfrHQB1f-yckpfGKue"
    }
  ]
}

或者

GET /colors/_mget
{
  "docs": [
    {
      "_id": 1
    },
    {
      "_id": 2
    }
  ]
}

代价较小的批量操作

bulkAPI允许在单个步骤中进行多次修改操作。

bulk请求格式如下:

{ action: { metadata }}\n
{ request body        }\n
{ action: { metadata }}\n
{ request body        }\n
...
POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }} 
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title":    "My first blog post" }
{ "index":  { "_index": "website", "_type": "blog" }}
{ "title":    "My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} } 

注意:

  • delete动作不能有请求体,其后面跟着的是另外一个操作;
    最后一个换行符不能落下。

参考:https://www.cnblogs.com/sandea/p/10412001.html


分布式文档存储

文档路由

es通过hash计算决定文档具体落在哪个shard中。计算公式为:

shard = hash(routing) % number_of_primary_shards

其中routing是一个可变值,默认为文档的_id,也可以设置为自定义值。

这就解释了为什么创建索引的时候一旦shards数量确定后就不能再修改:因为如果shards数量改变后,那么所有之前路由的值都会无效,文档将再也找不到

另外,所有文档API都接受一个routing的路由参数,通过这个参数可以自定义文档到分片的映射。通过自定义路由可以将相关的文档--例如属于同一个用户的文档都被存储到同一个分片中。

参考:ElasticSearch——路由(_routing)机制

主副分片交互

假设现有集群由三个节点组成。索引blog有两个主分片,每个主分片有两个副本分片。相同分片的副本不会放在同一个节点。具体如下图所示:

可以发送请求到集群中的任意节点。每个节点都有能力处理任意请求,每个节点都能知道集群中任一文档的位置,所以可以直接将请求转发到需要的接点上。在上面例子中,将所有的请求发送到node1节点,我们称之为协调节点(coordinating node)

写一致性和quorum机制

在主分片或副本分片上成功创建、索引和删除文档所需要的步骤顺序:

  • 客户端向Node1发送新建、索引或删除请求;
  • 节点使用文档_id确定文档属于哪个分片,比如此处是分片0。请求会被转发到Node3,因为分片0的主分片被分配在Node3上;
  • Node3在主分片上执行请求。如果成功了,其将请求并行转发到Node1和Node2的副本分片上,一旦所有的副本都报告成功,Node3将向协调节点报告成功,协调节点向客户端报告成功。

在客户端收到成功响应时,文档变更已经在主分片和副本分片执行完成,此次变更是安全的。

es提供参数consistency来确定具体多少分片处于活跃可用状态(其中分片可以是主分片或副本分片),才会去执行操作。

consistency有三种值:

  • one:此次操作主需要有一个primary shard是active的,就可以执行;
  • all:此次操作必须所有的primary shard和replica shard都是active的,才能执行;
  • quorum:默认值。要求所有的shard中,必须是大部分的shard是active的,才能执行。

quorum机制

quorum机制,写之前确保大部分的shard是可用的。其数量为int((primary+number_of_replicas)/2) + 1,且number_of_replicas > 1才会生效。

例如:1个primary shard,number_of_replicas=3,总共有4个shard。quorum = int((1 + 3) / 2) + 1 = 3,所有要求至少3个shard是active状态的,才能执行写操作。 如果节点数量少于quorum,那么可能导致无法执行任何写操作。

es提供了特殊的场景,number_of_replicas > 1才会生效。假如一个primary shard,number_of_replicas=1,那么此时quorum=2,但是如果此时只有一个node,那么此时只能有一个shard是active的(主shard和其对应的副本shard不能在同一个节点上),此时可能会导致单节点无法工作。

例如,在3个节点的集群上创建索引:

PUT customer5
{
  "settings": {
    "number_of_replicas": 3,
    "number_of_shards": 1
  }
}

此时通过命令GET _cluster/health/customer5查看索引的状态为yellow:

{
  "cluster_name" : "es-docker-cluster",
  "status" : "yellow",
  "timed_out" : false,
  "number_of_nodes" : 3,
  "number_of_data_nodes" : 3,
  "active_primary_shards" : 1,
  "active_shards" : 3,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 1,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 90.74074074074075
}

通过命令GET _cat/shards/customer5?v查看shard分配情况:

index     shard prirep state      docs store ip         node
customer5 0     r      STARTED       0  208b 172.21.0.3 es01
customer5 0     p      STARTED       0  208b 172.21.0.5 es02
customer5 0     r      STARTED       0  208b 172.21.0.2 es03
customer5 0     r      UNASSIGNED                       

可以看到有个shard副本没有分配。

取回一个文档

从主分片或者副本分片检索文档的步骤为:

  • 客户端向node1发送获取请求;
  • 节点使用文档的_id来确定文档属于分片0。分片0的副本分片分布在3个节点上。此时,它将请求转发到node2;
  • node2将文档返回node1,然后将文档返回给客户端。

在处理读取请求时,协调结点在每次请求的时候都会通过轮询所有的副本分片来达到负载均衡

在文档被检索时,已经被索引的文档可能已经存在于主分片上但是还没有复制到副本分片。 在这种情况下,副本分片可能会报告文档不存在,但是主分片可能成功返回文档。 一旦索引请求成功返回给用户,文档在主分片和副本分片都是可用的。


搜索

分页

es提供了sizefrom两个参数:

  • size:显示应该返回的结果数量,默认10
  • from:显示应该跳过的初始结果的数量,默认0

如果每页展示 5 条结果,可以用下面方式请求得到 1 到 3 页的结果:

GET /_search?size=5
GET /_search?size=5&from=5
GET /_search?size=5&from=10

分布式系统中的深度分页

我们可以假设在一个有 5 个主分片的索引中搜索。当我们请求结果的第一页(结果从 1 到 10 ),每一个分片产生前 10 的结果,并且返回给 协调节点,协调节点对 50 个结果排序得到全部结果的前 10 个。

现在假设我们请求第 1000 页,结果从 10001 到 10010 。所有都以相同的方式工作除了每个分片不得不产生前10010个结果以外。 然后协调节点对全部 50050 个结果排序最后丢弃掉这些结果中的 50040 个结果。

可以看到,在分布式系统中,对结果排序的成本随分页的深度成指数上升。这就是 web 搜索引擎对任何查询都不要返回超过 1000 个结果的原因。


请求体查询

查询和过滤

  • 过滤:只是简单的检查包含或排除,不需要计算评分,计算非常快。并且结果被会缓存到内存中以便快速读取;
  • 查询:不仅要找到匹配的文档,还要计算每个匹配的文档的相关性。同时,结果不会被缓存。

通常,使用查询(query)语句来进行全文搜索或者其它任何需要影响相关性得分的搜索。除此以外的情况都使用过滤(filters)。

分布式检索

文档可能在集群的任何分片上。一个搜索请求必须询问索引的所有分片的某个副本来确定他们是否含有任何匹配的文档。
但是,找到匹配的文档只是完成搜索的一半。在search接口返回一个page结果之前,多分片中的结果必须组合成单个排序列表。为此,搜索被执行成一个两阶段过程:query then fetch。

查询阶段

查询阶段包括以下三个步骤:

  • 客户端发送一个search请求到node3,node3会创建一个大小为size+from的空优先队列;
  • node3将查询请求转发到索引的每个主分片或者副本分片中。每个分片在本地执行查询并且添加结果到大小为size+from的本地有序优先队列中;
  • 每个分片返回各自优先队列中所有文档的id和排序值给协调节点,也就是node3,它合并这些值到自己的优先队列中产生一个全局排序后的结果列表。

第一步是广播请求到索引中的每一个节点的分片拷贝。查询请求可以被某个主分片或副本分片处理,这就是为什么更多的副本能够增加搜索吞吐率。协调节点将在之后的请求中轮询所有的分片拷贝来分摊负载。

然后分片返回一个轻量级的结果列表到协调节点,仅包含文档id和任何排序需要用到的值,如_score等。

优先队列:
一个优先队列仅仅是一个存有top-N匹配文档的有序列表。优先队列的大小取决于分页参数from和size。例如如下搜索请求将需要足够大的优先队列来存放100条文档:

GET /_search
{
  "from": 90,
  "size": 10
}

取回阶段

查询阶段标识了哪些文档满足搜索请求,但是仍然需要取回这些文档。

取回阶段有以下几个步骤:

  • 协调节点辨别出哪些文档需要被取回并向相关的分片提交多个GET请求;
  • 每个分片加载并丰富文档,如果有需要的话,接着返回文档给协调节点;
  • 一旦所有的文档都被取回,协调节点返回结果给客户端。

协调节点首先决定哪些文档 确实 需要被取回。例如,如果我们的查询指定了{ "from": 90, "size": 10 },最初的90个结果会被丢弃,只有从第91个开始的10个结果需要被取回。这些文档可能来自和最初搜索请求有关的一个、多个甚至全部分片。

协调节点给持有相关文档的每个分片创建一个multi-get request,并发送请求给同样处理查询阶段的分片副本。

分片加载文档体,_source字段等丰富结果文档。一旦协调节点收到所有的结果文档,它就组装这些结果为单个响应返回给客户端。

游标查询(scroll)

游标查询允许我们 先做查询初始化,然后再批量地拉取结果。

游标查询会取某个时间点的快照数据。 查询初始化之后索引上的任何变化会被它忽略。 它通过保存旧的数据文件来实现这个特性,结果就像保留初始化时的索引『视图』一样。

深度分页的代价根源是结果集全局排序,如果去掉全局排序的特性的话查询结果的成本就会很低。 游标查询用字段 _doc 来排序。 这个指令让 es 仅仅从还有结果的分片返回下一批结果。

启用游标查询可以通过在查询的时候设置参数 scroll 的值为我们期望的游标查询的过期时间。 游标查询的过期时间会在每次做查询的时候刷新,所以这个时间只需要足够处理当前批的结果就可以了,而不是处理查询结果的所有文档的所需时间。 这个过期时间的参数很重要,因为保持这个游标查询窗口需要消耗资源,所以我们期望如果不再需要维护这种资源就该早点儿释放掉。 设置这个超时能够让 es 在稍后空闲的时候自动释放这部分资源。

GET /old_index/_search?scroll=1m // 1
{
    "query": { "match_all": {}},
    "sort" : ["_doc"],  // 2
    "size":  1000
}

说明:

  • 保持游标查询窗口为1分钟;
  • 关键字_doc是最有效的排序顺序。

这个游标查询返回的下一批结果。 尽管指定字段 size 的值为1000,但是有可能取到超过这个值数量的文档。 当查询的时候, 字段 size 作用于单个分片,所以每个批次实际返回的文档数量最大为 size * number_of_primary_shards

索引管理

重新索引数据

别名


分片内部原理

使文本可被搜索

传统的数据库每个字段存储单个值,但这对全文检索并不够。文本字段中的每个单词需要被检索,对数据库意味着需要单个字段有索引多个值的能力。

倒排索引包含了一个有序列表,列表包含所有文档出现的不重复个体。它还保存了每一个词项出现过的文档总数,在对应的文档中一个具体词项出现过的总次数,词项在文档中的顺序,每个文档的长度,所有文档的平均长度等。这些统计信息允许es作为相关性的计算。

不变性

倒排索引被写入磁盘后是不可改变的。其优点有:

  • 不需要锁。不需要担心多个线程同时修改数据的问题;
  • 一旦索引被读入内核的文件系统缓存,只要文件系统缓存中还有足够的空间,那么大部分读取请求会直接请求内存,而不会去命中磁盘。这提供了很大的性能提升;
  • 其他缓存(像filter缓存),在索引的生命周期内始终有效。他们不需要在每次数据改变时被重建,因为数据不会变化;
  • 写入单个大的倒排索引允许数据被压缩,减少磁盘IO和需要被缓存到内存的索引的使用量。

动态更新索引

既然倒排索引不能更改,那么如果实现倒排索引的更新呢?
使用更多的索引

通过增加新的索引来反映新建的索引,而不是直接重写整个倒排索引。每一个倒排索引都会被轮流查询(从最早的开始),查询完后再对结果进行合并。

es基于Lucene,其提供了段(segment)的概念,每一段本身是一个倒排索引,但索引在Lucene里除了是段的集合外,还包含提交点(commit point),其指出了所以已知的段文件。

逐段搜索会有如下流程:

  • 新文档被放到内存索引缓存;
  • 缓存定期被提交:
    • 一个新的段(一个追加的倒排索引)被写入磁盘;
    • 一个新的包含新段名字的提交点被写入磁盘;
    • 磁盘进行同步,所有在文件系统缓存中等待的写入都会刷新到磁盘,以确保文件不会丢失。
  • 新的段被开启,让它包含的文档能够被搜索;
  • 内存缓存被清空,等待接收新的文档。

一个在内存缓存中包含新文档的Lucene索引:

在一次提交后,一个新的段被添加到提交点而且缓存被清空:

当一个查询被触发,所有已知的段按照顺序被查询。词项统计会对所有段的结果进行聚合,以保证每个词和每个文档的关联都被准确计算。这种方式可以用相对较低的成本将新文档添加到索引。

删除和更新

段是不能改变的,所以既不能将文档从旧的段中删除,也不能修改旧的段来反映文档的更新。取而代之的是,每个提交点会包含一个.del文件,文件中会列出这些被删除文档的段信息

当一个文档被『删除』,其实际上只是在.del文件中被标记为删除。一个被标记删除的文档仍然可以被查询匹配到,但是它在最终结果被返回前从结果集中移除。

文档更新也是类似的操作:当一个文档被更新时,旧版本文档被标记删除,文档的新版本被索引到一个新的段中。可能两个版本的文档都会被一个查询匹配到,但被删除的那个旧版本文档在结果集返回前就已经被移除。

近实时搜索

提交一个新的段到磁盘需要一个fsync来确保段被物理性地写入磁盘,这样断电后数据也不会丢失。但是fsync操作代价很大,如果每次索引一个文档都去执行一次的话会造成很大的性能问题。

在es和磁盘之间是文件系统缓存,在内存索引缓冲区中的文档被写入到一个新的段中,但是这里段会被先写入到文件系统缓存中,这一步的代价会比较低,稍后再被刷新到磁盘,这一步的代价比较高。不过只要文件已经在缓存中,就可以像其他文件一样被打开和读取了

Lucene允许新段被写入和打开,这样使其包含的文档在未进行一次完整的提交时便对搜索可见。这种方式比进行一次提交代价要小得多,并且在不影响性能的前提下可以被频繁地执行

refresh API

在es中,写入和打开一个新段的轻量的过程叫做refresh。默认情况下每个分片会每秒自动刷新一次,这就是es是近实时搜索的原因:文档的变化并不是立即对搜索可见,但会在一秒之内变为可见

为了让索引立即可见,可以调用refresh API执行一次手动刷新:

POST /_refresh  // 刷新所有索引
POST /test_index/_refresh   // 刷新指定索引

尽管刷新操作相比提交是一个轻量很多的操作,但是仍然有性能开销。再生产环境上应该避免。

并不是所有的情况都需要每秒刷新。比如说使用es索引大量的日志文件,追求的是索引速度而不是近实时搜索,此时可以通过设置refresh_interval,降低每个索引的刷新频率:

PUT /my_index
{
  "settings": {
    "refresh_interval": "30s"  //每30s刷新一次
  }
}

refresh_interval可以在既存索引上进行动态更新。在生产环境中,当正在建立一个大的新索引时,可以先关闭自动刷新,待开始使用该索引时,再把它们调回来,"refresh_interval": -1表示关闭自动刷新。

持久化变更

如果没有用 fsync 把数据从文件系统缓存刷(flush)到硬盘,我们不能保证数据在断电甚至是程序正常退出之后依然存在。为了保证 Elasticsearch 的可靠性,需要确保数据变化被持久化到磁盘。

一次完整的提交会将段刷新到磁盘,并写入一个包含所有段列表的提交点。es在启动或者重新打开一个索引的过程中使用这个提交点来判断哪些段隶属当前分片。

但是,两次完整的提交之间系统宕机或退出了怎么办?这部分的数据不希望丢失。

es增加了事务日志(translog),每一次对es进行操作时均进行了日志记录。通过事务日志,整个流程如下:

  • 一个文档被索引之后,就会被添加到内存缓冲区,并且 追加到了 translog

  • 刷新分片:

    • 在内存缓冲区中的文档被写入到一个新的段中,且没有执行fsnyc操作;
    • 这个段被打开,使其可被搜索;
    • 内存缓冲区被清空。
  • 这个进程继续工作,更多的文档被添加到内存缓冲区和追加到事务日志;

  • 每隔一段时间—​例如 translog 变得越来越大—​索引被刷新(flush);一个新的 translog 被创建,并且一个全量提交被执行:

    • 所有在内存缓冲区的文档都被写入到一个新的段;
    • 缓冲区被清空;
    • 一个提交点被写入磁盘;
    • 文件系统缓存通过fsync被刷新(flush);
    • 老的translog被删除。

translog 提供所有还没有被刷到磁盘的操作的一个持久化纪录。当 Elasticsearch 启动的时候, 它会从磁盘中使用最后一个提交点去恢复已知的段,并且会重放 translog 中所有在最后一次提交后发生的变更操作。

translog 也被用来提供实时 CRUD 。当你试着通过ID查询、更新、删除一个文档,它会在尝试从相应的段中检索之前,首先检查 translog 任何最近的变更。这意味着它总是能够实时地获取到文档的最新版本。

flush API

执行一次提交并且截断translog的行为在es被称为一次flush。分片每30min会自动刷新,或者在translog太大的时候也会刷新。

POST /blogs/_flush 

POST /_flush?wait_for_ongoing // 刷新所有索引并且等待所有刷新在返回前完成

在节点重启或关闭索引之前执行flush有益于索引。因为es尝试恢复或重新打开一个索引,需要重放translog中所有的操作,所以如果日志越短,恢复越快。

translog有多安全?
在文件被 fsync 到磁盘前,被写入的文件在重启之后就会丢失。默认 translog 是每 5 秒被 fsync 刷新到硬盘, 或者在每次写请求完成之后执行(e.g. index, delete, update, bulk)。这个过程在主分片和复制分片都会发生。最终, 基本上,这意味着在整个请求被 fsync 到主分片和复制分片的translog之前,客户端不会得到一个 200 OK 响应。
但是对于一些大容量的偶尔丢失几秒数据问题也并不严重的集群,使用异步的 fsync 还是比较有益的。比如,写入的数据被缓存到内存中,再每5秒执行一次 fsync 。

PUT /my_index/_settings
{
    "index.translog.durability": "async",
    "index.translog.sync_interval": "5s"
}

这个选项可以针对索引单独设置,并且可以动态进行修改。参数默认为:"index.translog.durability": "request"

段合并

由于自动刷新流程每秒会创建一个新的段 ,这样会导致短时间内的段数量暴增。而段数目太多会带来较大的麻烦。 每一个段都会消耗文件句柄、内存和cpu运行周期。更重要的是,每个搜索请求都必须轮流检查每个段;所以段越多,搜索也就越慢。

Elasticsearch通过在后台进行段合并来解决这个问题。小的段被合并到大的段,然后这些大的段再被合并到更大的段。

段合并的时候会将那些旧的已删除文档从文件系统中清除。被删除的文档(或被更新文档的旧版本)不会被拷贝到新的大段中

段合并流程:

  • 当索引的时候,刷新(refresh)操作会创建新的段并将段打开以供搜索使用;
  • 合并进程选择一小部分大小相似的段,并且在后台将它们合并到更大的段中。这并不会中断索引和搜索。例如:两个提交了的段和一个未提交的段正在被合并到一个更大的段;
  • 一旦合并结束,老的段被删除:
    • 新的段被刷新到了磁盘,写入一个包含新的段且排除旧的和较小的段的新的提交点;
    • 新的段被打开用来搜索;
    • 老的段被删除。

合并大的段需要消耗大量的I/O和CPU资源,如果任其发展会影响搜索性能。Elasticsearch在默认情况下会对合并流程进行资源限制,所以搜索仍然 有足够的资源很好地执行。

optimize API

强制合并API。它会将一个分片强制合并到 max_num_segments 参数指定大小的段数目。 这样做的意图是减少段的数量(通常减少到一个),来提升搜索性能。

在特定情况下,使用 optimize API 颇有益处。例如在日志这种用例下,每天、每周、每月的日志被存储在一个索引中。 老的索引实质上是只读的;它们也并不太可能会发生变化。

在这种情况下,使用optimize优化老的索引,将每一个分片合并为一个单独的段就很有用了;这样既可以节省资源,也可以使搜索更加快速:

POST /logstash-2014-10/_optimize?max_num_segments=1

标签:节点,索引,文档,分片,elasticSearch,查询,基本概念,es
From: https://www.cnblogs.com/shitianming/p/17991586

相关文章

  • logstash实现Mysql(Tidb)数据到Elasticsearch数据迁移(增量同步)
    1、下载Logstash和Elasticsearch,需要版本一致,本次使用版本均为7.8.0版本[root@zjkdata]#llelasticsearch-7.8.0-linux-x86_64.tar.gzlogstash-7.8.0.tar.gz-rw-r--r--.1rootroot31911256112月2815:39elasticsearch-7.8.0-linux-x86_64.tar.gz-rw-r--r--.1root......
  • linux 安装 elasticsearch
    安装Elasticsearch在Linux系统上的步骤如下:首先,确保你的系统已经安装了Java,Elasticsearch是基于Java开发的,所以需要先安装Java运行环境。可以使用以下命令来检查Java是否已经安装:java-version如果Java已经安装,将会显示Java版本信息。如果没有安装,请根据你的系统......
  • 【docker-compose】ElasticSearch安装教程
    仅供学习参考,请勿轻易在生产环境使用0.目录树1.创建目录mkdir-p/docker/elasticsearch/conf/docker/elasticsearch/data/docker/elasticsearch/logschmod-R777/docker/elasticsearch/conf/docker/elasticsearch/data/docker/elasticsearch/logs2.编写配置......
  • 详解ElasticSearch Python Client ReadTimeout
    详解ElasticSearchPythonClientReadTimeout在使用Python连接Elasticsearch时,我们经常会遇到一些异常情况,其中之一就是ReadTimeout错误。本文将详细介绍这个错误的原因以及如何处理。什么是ReadTimeout错误?ReadTimeout错误通常是由Elasticsearch连接超时引起的。当在与Elasticsea......
  • 什么是大模型?一文读懂大模型的基本概念
    大模型是指具有大规模参数和复杂计算结构的机器学习模型。本文从大模型的基本概念出发,对大模型领域容易混淆的相关概念进行区分,并就大模型的发展历程、特点和分类、泛化与微调进行了详细解读,供大家在了解大模型基本知识的过程中起到一定参考作用。本文目录如下:·大模型的定义......
  • elasticsearchjava客户端
    elasticsearchjava客户端1.引用maven配置<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><exclusions><exclusion>&l......
  • 用CI/CD工具Vela部署Elasticsearch + C# 如何使用
    Vela除了可以帮我们编译、部署程序,利用它的docker部署功能,也能用来部署其他线上的docker镜像,例如部署RabbitMQ、PostgreSql、Elasticsearch等等,便于集中管理。部署Elasticsearch创建文件夹并赋予权限:mkdir/usr/local/es/datamkdir/usr/local/es/pluginschmod777/usr/......
  • 数据仓库基本概念
    什么是数据仓库?数据仓库,英文名称为DataWarehouse,数据仓库(DataWarehouse)是一个面向主题的(SubjectOriented)、集成的(Integrated)、相对稳定的(Non-Volatile)、反映历史变化(TimeVariant)的数据集合,用于支持管理决策(DecisionMakingSupport)。——比尔·恩门(BillInmon)......
  • Elasticsearch-Mapping篇
    官方文档官网:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html映射是定义文档及其包含的字段如何存储和索引的过程。每个文档都是字段的集合,每个字段都有自己的数据类型。映射数据时,您创建一个映射定义,其中包含与文档相关的字段列表。映射定义......
  • 等保基本概念
    等级保护指对国家重要信息、法人和其他组织及公民的专有信息以及公开信息和存储、传输、处理这些信息的信息系统分等级实行安全保护,对信息系统中使用的信息安全产品实行按等级管理,对信息系统中发生的信息安全事件分等级响应、处置。我国实行网络安全等级保护制度,等级保护对象分为......