Elasticsearch索引与文档

导读:本篇文章讲解 Elasticsearch索引与文档,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

概述

在Elasticsearch中,索引和文档是REST接口操作的最基本资源。索引一般是以索引名称出现在REST请求操作的资源路径上,而文档则是以文档ID为标识出现在资源路径中。除了这两种资源,映射类型_doc也可以认为是一种资源。但在Elasticsearch 7 废除映射类型的大背景下,_doc已经越来越接近于一种接口名称。与_doc类似的还要_alias、_settings、_update等,它们虽然也会出现在REST请求的路径上,但并不是一种实际的资源。在学习时可以把它们当做是REST操作的一种虚拟资源,或者干脆就把它们当成是一种REST接口,它们实现了对索引和文档的创建、删除、修改等操作。

索引别名与配置

在Elasticsearch中,可以使用四种HTTP方法请求索引,即PUT、GET、DELETE和HEAD。其中,PUT请求用于创建索引;GET请求用于查看索引;DELETE请求用于删除索引;HEAD请求有点特殊,用于索引存在性检验,如果索引存在则返回200状态码,否则返回404状态码,如下:

PUT test
GET test
HEAD test
DELETE test

索引名称不可以随意命名,在创建索引是有一些重要的命名限制需要引起注意,具体如下:

  • 索引名称只能使用小写字母。
  • 索引名称不能包括:\,/,*,?,”,<,>,|,‘’(空格),,(逗号),#;
  • 在7.0版本之后不可以包含冒号;
  • 索引名称不能以下列符号开头:-,_,+;
  • 索引名称不能使用“.”或”…”;
  • 索引名称长度必须小于255B。
    在实际使用中,一般不会像示例那样只使用PUT请求创建索引而不对索引做任何配置。因为在向一个索引添加文档时,如果索索引不存在Elasticsearch会自动将这个索引创建出来。所以如果接受索引的默认参数,完全可以等到添加文档时由Elasticsearch自动创建。任何一个索引都包括别名、映射和配置三个参数,它们可在创建索引时使用aliases、mappings和setting设置。映射(mappings)已经在之前做了详细介绍,本节主要介绍索引的别名和配置。

索引别名

索引别名可以类比为传统关系型数据库中的视图,Elasticsearch在处理别名时会自动将别名转换为对应的索引名称。所以如果别名与索引完全相同,它就没有存在的意义。因此与视图类似,索引别名一般都会与一些过滤条件相关联。过滤条件可以使用文档查询语句,比如term、match等。例如,创建students索引存储学生信息,并根据性别添加男生和女生别名:
在这里插入图片描述
students索引一共关联了girls和boys两个别名。在别名的定义中,filter用于定义过滤器,routing用于定义路由规则,它们将在使用别名检索时自动应用。在定义过滤条件时通常要指定路由规则,这样会将同一别名的文档路由到相同的分片上,可以有效减少使用别名检索时的分片操作。但这也要求在存储文档时必须要通过别名,否则在使用别名检索时有可能会漏掉合法文档。例如使用students添加文档而使用girls、boys检索文档,就有可能会出现检索不到文档的情况发生,读者可以自己试一下。
别名并不一定只与一个索引关联,它可以与多个索引关联,这种设计在一些应用场景中十分有价值。比如索引容量规则时曾经提到,如果文档数量整体容量不可估算并且每天都在增加,可以按时间段每隔一段时间就创建一个新索引。这虽然解决了索引容量问题,但带来的问题就是在检索时需要指定多个索引。有了索引别名就可以给这些同属一个领域的索引关联相同的别名,这样在检索文档时就可以对它们共同的别名做检索,避免了不停变换索引名称带来的麻烦。
索引别名不仅可以在创建索引时指定,也可以在索引创建后再动态添加或删除。下面就来看看这些有关别名的接口。

_alias和_aliases接口

在索引创建后,_alias和_aliases接口都可以用于添加或删除别名,不同的是前者一般针对某一具体的索引,而后者可以对多个索引做批量操作。例如,为索引students添加一个代表一年级的别名grade1:
在这里插入图片描述
PUT请求的资源为“/students/alias/grade1”,资源中使用_alias表明这是一个对别名资源操作的请求,并且确定了索引为students而别名为grade1。资源中的索引名可以使用_all来代表所有索引,也可以使用类似“log*”这样的形式匹配多个索引。一般情况下,使用PUT或POST方法请求上述资源时是添加别名,别名的过滤条件、路由等配置信息则在请求体中以filter、routing参数定义;使用DELETE方法则是删除别名,不需要使用请求体;使用GET方法请求“/students/_alias”,可以查看students索引的所有别名。Elasticsearch的CAT接口提供“_cat/aliases”接口,以GET方法访问接口会以纯文本形式返回所有别名。
下面再来看一看_aliases接口如何实现相同的需求,如示例3-4所示:
在这里插入图片描述
_aliases接口请求的资源中也可以添加索引名称,例如“/students/_aliases”代表只针对students索引做操作。_aliases接口的请求体接收数组类型的actions参数,它可以指定的行为包括add、remove、remove_index等,分别对应添加别名、删除别名和删除索引等行为。示例3-4只给出了单个索引对应单个别名的情况,实际上还可以通过indices和aliases指定多个索引和多个别名。所以_aliases接口可以针对多个索引、多个别名,实现添加、删除等多种操作。

_rollover接口

rollover接口用于根据一系列条件将别名指向一个新的索引,这些条件包括存续时间、文档数量和存储容量等。这与日志文件使用的文件滚动类似,文件滚动是通过不断创建新文件并滚动旧文件来保证日志文件不会过于庞大,而_rollover接口则是通过不断将别名指向新的索引以保证索引容量不会过大。这其实是容量规划时提到的无限容量存储的一种解决方案,但这种别名滚动并不会自动完成,需要主动调用_rollover接口。
别名滚动的条件可通过conditions参数设置,包括max_age、max_docs和max_size等三个子参数。例如,创建一个索引logs-1并分配别名logs,然后调用logs别名的_rollover接口设置别名滚动条件,如示例3-5
在这里插入图片描述
logs别名指向logs-1索引,最大存活周期为14天,最大文档数量10000条,最大存储容量4GB。因为logs-1索引刚刚创建,存活时间、文档数量和存储容量都不满足条件,所以使用示例的请求不会对logs别名产生任何影响。这通过请求返回的结果也可以看到:
在这里插入图片描述
从返回结果的conditions属性来看,三个条件匹配的结果都是false,所以不会触发索引滚动。如果想体验别名滚动的效果,可以将max_age设置为1 s再调用上面的请求。之后通过“GET _cat/indices”接口就会发现有新的索引logs-000002产生,再分别查看这两个索引就会发现,logs-1的别名已经被清空,而logs-000002的别名中则已经添加了logs。新索引的命名规则在原索引名称数字的基础上加1,并且将数值长度补0凑足6位。所以使用_rollover接口时,要求索引名称必须以数字结尾,数字与前缀之间使用连接线“-”连接,即满足正则表达式“^.*- \ d+$”。如果索引名称没有遵从这样的规则,则需要在调用_rollover接口时指定新索引名称,例如:
在这里插入图片描述
由于_rollover接口在滚动新索引时,会将别名与原索引的关联取消,所以通过别名再想查找已经编入索引的文档就不可能了。为了保证原文档可检索,可以通过别名is_write_index参数保留索引与别名的关系。当使用is_write_index参数设置了哪一个索引为写索引时,_rollover接口滚动别名指向索引时将不会取消别名与原索引之间的关系。它会将原索引的is_write_index参数设置为false,并将新索引的is_write_index参数设置为true。例如在创建logs-1时添加参数如示例3-8所示:
在这里插入图片描述
再执行示例3-5中的请求时,会发现logs-1的is_write_index参数被设置为false,而新生成索引logs-000002的is_write_index参数则为true。在两者的别名列表中都包含有logs,可以继续通过logs别名对原索引进行查询。

索引配置

索引的settings参数用于添加索引配置,索引的所有配置项都以“index”开头,在设置这些配置项时也可以通过JSON对象的形式来编写。例如,在示例3-9中两种创建索引的方式都是正确的。
在这里插入图片描述
索引配置包括静态配置和动态配置两种,静态配置只能在索引创建时或索引关闭时设置,而动态配置没有这个限制。

索引关闭或打开

索引可以被关闭,关闭后的索引除了维护自身元数据信息以外,基本上不会再占用集群资源,同时也不能再被用户读写。索引关闭后可以再次打开,所以通过关闭索引可以实现索引存档的目的。Elasticsearch提供了索引关闭与打开的REST接口,例如:
在这里插入图片描述
test为任意索引名称。索引名称可以使用_all或号将所有索引关闭或打开,但如果配置文件中设置了action.destructive_requires_name为true,则在这里就不能使用_all或号;如果配置文件中设置cluster.indices.close.enable为false,则索引将不能被关闭。

索引静态配置

索引静态配置主要有索引主分片、压缩编码、路由等相关信息的参数,他们只能在创建索引时设置,一旦索引创建完成就不能再修改静态配置。具体静态配置参数见下表,其中配置参数都以index开头。
在这里插入图片描述

索引动态配置

Elasticsearch为查询和修改索引配置提供_settings接口,以GET方法请求_settings接口时可获取索引配置信息,而以PUT方法访问时则可以修改配置。调用该接口时可以在路径中添加一个或多个索引名称,这时请求将只针对某一或某些索引,否则请求将针对所有索引。示例3-11展示了使用_setting接口查询和修改test索引的配置项:
在这里插入图片描述
在查询配置时还可以在地址中添加flat_settings参数,这可以使返回结果的JSON对象被平铺展示,以使结果更加紧凑。flat_settings参数默认值是false,一般在使用程序读取结果时可将它设置为true。同时这个参数是一个通用参数,在其他查看配置的接口中使用也有效,比如GET _cluster/settings?flat_settings。
修改索引配置项只能针对动态配置项,静态配置项一旦设置好了就不能再修改。对于某些动态配置项,还需要先将索引关闭才能更新。动态配置可以通过更新索引配置接口随时更改,具体的索引动态配置项见表3-2。
在这里插入图片描述
这些参数中,number_of_replicas和auto_expand_replicas用于设置副本分片数量,这在本书第2章2.4.4节中已有介绍。search.idle.after和refresh_interval则会影响到索引的刷新频率,在本书第2章2.1.3节在讲索引时曾经有过简单的介绍,但实际上这两个参数并不针对索引而是针对索引中具体的某一个分片。如果一个索引分片没有接收到数据查询的请求,那么它会一直等到search.idle.after参数设置的时间后才有可能去刷新索引。当然如果在这段时间有新的数据检索请求,索引就会与其他索引一起做刷新。search.idle.after参数是在Elasearch 7之后才加入的新参数,目的是为了提升索引刷新的性能。由于这种处理机制只有在refresh_interval参数没有设置明确值时才会起作用,所以如果不想使用这种机制,可以明确地将refresh_interval参数设置为1s。其余参数大多与具体的查询语言相关,它们将在讲解到查询语言时再做介绍。

动态映射与索引模板

索引并非一定要先创建才能存储文档,可以在不创建索引的情况下直接向索引中添加文档。Elasticsearch的动态映射机制会根据文档内容,并依据索引模板自动创建一个与文档相匹配的索引。如果不希望Elasticsearch自动创建索引,可以通过在elasticsearch.yml配置文件中将action.auto_create_index参数设置为false来禁止。这个参数还可以接收“+shop_,-user_”这种形式的值,其中加号“+”代表允许自动创建索引,而减号“-”则代表不允许。所以“+shop_,-user_”的意思就是允许以“shop_”开头的索引自动创建,而不允许“user_”开头的索引自动创建。此外,_cluster接口也提供了动态修改这个配置的方法:
在这里插入图片描述
动态映射依赖一些预定义的动态字段类型映射规则,同时还可以使用动态字段模板自定义字段类型映射。如果希望在创建索引时自动应用某些配置信息,可使用索引模板定义创建索引时默认添加的别名、配置和映射关系。

动态字段

即使在索引创建后,Elasticsearch依然支持向索引中增加新字段,这种动态增加字段的特性可通过dynamic参数来修改。dynamic参数可以设置在映射类型上,或是对象类型的字段上,可选值为true、false和strict,默认值是true。当dynamic设置为false时,新增加的字段将会被忽略;而设置为strict时则会抛出异常。例如下面示例将动态添加字段功能关闭了,所有未在properties中定义的新字段都将被忽略:
在这里插入图片描述
需要注意的是,当dynamic设置为false,在添加新文档时出现的新字段依然会被保存到文档中,只是这个字段的定义并不会被添加到索引映射的字段定义中。只有当dynamic为true时,新添加字段才会按一定的数据类型映射规则,将它们添加到索引映射的定义中。下表列表出了从JSON类型到Elasticsearch字段类型的对应关系:
在这里插入图片描述
如果字符中含有日期或数值,它们可以被解析为date或numeric类型。Elasticsearch默认对含有日期的字符串会自动解析为date类型,可以通过将映射的date_detection参数设置为false关闭解析。日期字符串在解析时使用的格式可通过dynamic_date_formats设置,默认值为
[“strict_date_optional_time”,“yyyy/MM/dd HH:mm:ss Z || yyyy/MM/dd Z”]。含有数值的字符串默认不会被解析为数值类型,但可通过numeric_detection参数开启数值解析。

动态模板

动态模板(Dynamic Template)用于自定义动态字段时的映射规则,可通过索引映射类型的dynamic_templates参数设置。该参数接受一组命名的动态模板,每一个模板由匹配条件和映射规则组成。匹配条件定义了新字段是否可以使用当前模板,可根据新字段的数据类型、名称和路径来定义条件;而映射规则由参数mapping定义,它需要给出新字段要使用哪些参数,可使用type定义新字段数据类型,也可以使用参数设置新字段其他特性。
匹配规则可使用关键字match_mapping_type匹配新字段数据类型,这可以用于将一种默认类型转换为其他类型或者设置其他特性。比如JSON整形默认会被映射为long,如果希望将整形映射为Integer可按下例所示:
在这里插入图片描述
在上列中,不仅将整形设置为integer类型,还将它的文档值机制关闭,即将doc_values参数设置为false。除了匹配新字段的数据类型,还可使用match、match_pattern和unmatch匹配新字段名称。其中match和unmatch可以使用星号”*”做名称匹配,而math_pattern则支持正则表达式。匹配新字段可使用path_match和path_unmatch,路径与名称的区别是其中包含点“.”。在mapping参数中,还可以使用{name}和{dynamic_type}代表新字段名称和类型。例如在示例3-15中keep_original动态模板将所有以“original_”开头字段的数据类型设置为原始类型:
在这里插入图片描述
需要注意的是,如果一个字段同时满足两个动态模板,它最终会应用在动态模板中先定义的那个规则。例如在示例3-15中,如果新添加字段名为“original_age”且类型为long,那么它就同时满足keep_original和to_integer两个模板 ,但它最终会应用第一个 模板keep_original,因为这个模板是先定义的。

索引模板

索引模板(Index Template)与动态模板不是一个概念,动态模板定义了索引创建后新添加字段的映射规则,而索引模板是在创建索引时默认为索引添加的别名、配置和映射等信息。索引模板包含该模板使用索引的模式或规则,以及索引创建时默认包含的别名、配置和映射关系等。它们分别通过index_patterns、aliases、settings和mappings等四个参数设置,可以通过_template接口创建。例如在示例3-16中创建一个名为user_tpl的索引模板:示例3-16 创建索引模板

PUT _template/user_tpl
{
	"index_patterns":["user*", "employee*"],
	"aliases":{
		"{index}_by_gender":{
			"filter":{
				"term":{
					"gender":"M"
				}
			}
		}
	},
	"settings":{
		"number_of_shards":1
	},
	"mappings":{
		"properties":{
			"gender":{
				"type":"keyword"
			}
		}
	}
}

在上例中,使用PUT方法请求的路径中,_template为索引模板接口的关键字,而后接的user_tpl则是模板名称。index_patterns参数定义了模板适用于名称以user或employee开头的索引,如果index_patterns在定义时出现规则重叠,索引创建时就有可能与多个模板匹配。比如定义一个匹配模式为“*”的模板all_tpl,那么当创建users索引时all_tpl和user_tpl就都满足匹配模式。Elasticsearch在处理这种冲突时,会将所有模板合并应用到索引上,这会导致后应用的模板规则覆盖先应用的模板规则。所以,索引模板提供了一个参数order用于指定合并应用的次序,如果不指定则order值为0.
aliases定义了默认将创建的索引别名,示例3-16创建了一个{index}_by_gender的别名,其中{index}是一个占位符,索引创建时将取索引实际名称替换。settings字段定义了默认配置,而mappings则定义了默认字段信息。在定义好这个模板后可通过”PUT users”请求创建索引,然后通过”GET users”查看索引信息会发现模板中预定义的别名、字段都出现在了索引的设置中。需要注意的是,模板仅在索引创建时使用,更改模板不会对已经创建的索引起作用。
_template接口也可以通过GET、DELETE和HEAD方法请求,分别用于对模板的查看、删除及存在性校验。此外,如果想要查看所有的模板,可以使用CAT接口,具体请求如下:

GET _template/user_tpl
HEAD _template/user_tpl
DELETE _template/user_tpl
GET _cat/templates

索引模板在Logstash和Beats组件向Elasticsearch传输数据时非常有用,它们基本上都会根据自身对索引的要求创建索引模板。

_mapping接口

索引的映射关系在索引创建后可通过_mapping接口查看或修改,可以访问该接口的请求方法包括GET、POST和PUT。使用GET方法访问时可以查看索引的映射类型及字段,请求资源的路径基本格式为“/<索引>/_mapping/<映射类型>/field/<字段>”。其中,_mapping为接口关键字必须使用,其余为可选项。如果没有指定索引名称而直接调用GET _mapping,将返回所有索引的映射关系。如果指定了索引名称则查看该索引的映射关系,指定了映射类型或字段则查看它们的映射关系。例如示例3-18中,第一个请求查看students所有的映射关系,而第二个请求则只查看其中的gender属性:3-18 查看映射关系

GET /students/_mapping
GET /students/_mapping/field/gender

使用PUT或POST方法请求_mapping接口时,可以向索引更新或添加字段,或修改已有字段的某些配置。例如在示例3-19的请求中,向students添加了age属性: 3-19 更新映射

put /students/_mappings
{
	"properties":{
		"age":{
			"type":"short"
		}
	}
}

在这种请求中,索引可以指定一个或多个。对已存在的映射关系只能添加字段或多类型,但字段一旦创建就不能删除。如果一定要删除某一个字段,唯一的办法是删除原索引后添加不包含该字段的新索引,然后再将原索引中的数据导入到新索引中做reindex。除了不能删除字段以外,字段的多数参数也不能修改,唯一可修改的参数是ignore_above。修改字段的方式与3-19一致,将要修改的参数放在字段配置中即可。
由此可见,在设计索引时一定要做好规划,在初始时可以只加入必要字段。为了隔离索引变化对用户的影响,可以只提供索引别名给用户访问,当索引发生变化时只需要把别名法分配到新索引就可以了。

容量控制与缓存机制

索引容量有分片数量和分片容量决定,分片数量可以通过_split接口扩容,也可以通过_shrink接口缩容。需要注意的是,这种扩容和缩容的方式依然是将原索引扩容、缩容到新索引上,并不是在原索引上做扩展;而且使用_split接口扩容时,分片扩容依然存在上限,如果增加分片的数量超过了容量上限,就只能通过_reindex接口对所有索引做重新索引。
除了这个三个可以直接或间接控制索引容量的接口以外,Elasticsearch为了提升性能还默认开启了缓存机制。

_split接口

_split接口可以在新索引中将每个主分片分裂为两个或更多分片,所以使用_split扩容时分片总量都是成倍增加而不能逐个增加。使用_split接口分裂分片虽然会创建新的索引,但新索引中的数据只是通过文件系统硬连接到新索引中,所以并不存在数据复制过程。而扩容的分片又是在本地分裂,所以不存在不同节点间网络传输数据的开销,所以_split扩容效率相对其他方案来说还是比较高效的。
_split接口做动态扩容需要预先设置索引的number_of_routing_shards参数,Elasticsearch向分片散列文档采用一致性哈希算法,这个参数实际上设置了索引分片散列空间。所以分裂后分片数量必须是number_of_routing_shards的因数,同时是number_of_shards的倍数。例如,设置number_of_routing_shards为12,number_of_shards为2,则分片再分裂存在2->4->12、2->6->12和2->12三种可能的扩容路径。分裂后分片数量可通过_split接口的index.number_of_shards参数设置,数量必须满足前述整数倍的要求。需要注意的是,这个参数的”index.”前缀是不能省略的,因为这是在_split接口中而不是在创建索引接口中。下面是一个例子:
首先创建一个索引employee,将它们的主分片数量number_of_shards设置为2,散列空间number_of_routing_shards设置为12。然后,通过将索引的blocks.write参数设置为true,将索引设置为只读,这是因为使用_split接口要求索引必须为只读。最后调用_split接口将employee索引的分片分裂到新索引splited_employee中,index.number_of_shards参数设置为4,即分裂为4个分片。如示例3-20所示:

DELETE employee
PUT employee
{
	"settings":{
		"number_of_shards":2,
		"number_of_routing_shards":12
	}
}
PUT /employee/_settings
{
	"blocks.write":true
}
PUT /employee/_split/splited_employee
{
	"settings":{
		"index.number_of_shards":4,
		"index.number_of_replicas":1,
		"index.blocks.write":false
	},
	"aliases":{
		"stu":{}
	}
}

在执行成功后,可调用“GET _cat/shards”查看分片。在返回结果中可以看到employee索引共用4个分片,即2个主分片和2个副分片;新索引splited_employee会有8个分片,即4个主分片和4个副分片。_split接口在创建新索引的同时,会将原索引的配置也一同设置到新索引中。所以index.blocks.write参数也会一同被复制过来,但这可能并不是我们想要的。所幸在分裂分片的同时支持通过aliases和settings设置新索引的别名和配置,所以可以在分裂分片的同时将index.blocks.write参数覆盖。在示例3-20中就将这个参数覆盖了,同时还添加了新的别名stu。另外,还可以在地址中添加copy_settings=false参数禁止从源索引中复制配置,但这个参数在版本8中有可能废止,所以添加这个参数会收到警告。
需要注意的是,使用_split接口成功分裂分片后,源索引并不会自动删除。通过原索引和新索引都可以查看到相同的文档数据,原索引是否删除应根据业务需要具体判断。

_shrink接口

与_split接口相反,_shrink接口用于缩减索引分片。尽管它们在逻辑上正好相反,但它们在应用时的规则基本上是一致的。比如,_shrink接口在缩减索引分片数量时也要求原始分片数量必须是缩减后分片数量的整数倍。例如原始分片数量为12,则可以按12→6→3→1的路径缩减,也可以按12→4→2→1的路径缩减。在调用_shrink接口前要满足两个条件,第一个条件与_split接口类似,就是要求索引在缩容期间必须只读;第二个条件有些特殊,就是要求索引所有分片(包括副本分片)都要复制一份存储在同一节点,并且要求健康状态为green,这可以通过routing.allocation.require._name指定节点名称实现。如果想要查看节点名称,可调用“GET _nodes”接口相看所有集群节点。
与_split接口类似,索引在缩减后的具体分片数量可通过_shrink接口的index.number_of_shards参数设置。但它的值必须与原始分片数量保持整数比例关系,如果不设置该参数将直接缩减为1个分片。如示例3-21所示,缩减后索引分片数量为2,同时还清除了两项配置:
在这里插入图片描述
同样地,使用_shrink接口缩容后会创建新索引shrinked_employee,原索引和新索引都可以查询到相同的文档数据。

_reindex接口

尽管_split接口和_shrink接口可以对索引分片数量做扩容和缩容,但在分片数量上有倍数要求,并且分片总量受限散列空间(即number_of_routing_shards参数)的限制。如果索引容量超出了散列空间或者有其他特殊要求,则可以按新需求创建新的索引。Elasticsearch提供的_reindex接口支持将文档从一个索引重新索引到另一个索引中。但显然重新索引在性能上的开销要把_split和_shrink大,所以尽量不要使用这种方法。_reindex接口需要两个参数source和dest,前者指明文档来源索引而后者则指明了文档添加的新索引。例如3-22中是将users索引中的文档添加到users_copy索引中:

POST _reindex
{
	"source":{
		"index":"users"
	},
	"dest":{
		"index":"users_copy"
	}
}

需要注意的是,在重新索引时,不会将原索引的配置复制到新索引中。如果事先没有指定索引配置,重新索引时将根据默认配置创建索引及映射。另外,使用_reindex接口必须将索引的_source字段开启。
在实际应用中,_reindex接口并不是应用于扩容和缩容,而是主要应用于索引数据的合并。所以在_reindex接口中还提供了一些其他参数,用于处理在合并过程中出现的问题。例如:

POST _reindex
{
	"conflicts":"proceed",
	"source":{
		"index":"users",
		"query":{
			"term":{
				"gender":{
					"value":"F"
				}
			}
		}
	},
	"dest":{
		"index":"users_copy",
		"op_type":"create"
	}
}

在示例中,source参数除了指定源索引以外还添加了term查询用于过滤文档,而dest参数则使用op_type参数设置了合并时只添加不存在的文档。

缓存机制

为了提升数据检索时的性能,Elasticsearch为索引提供了三种缓存。第一种缓存称为节点查询缓存(Node Query Cache),负责存储节点查询结果。节点查询缓存是节点级别的,一个节点只有一个缓存,同一节点上的分片共享同一缓存。在默认情况下,节点查询缓存是开启的,可通过索引index.queries.cache.enabled参数关闭。节点查询缓存默认使用节点内存的10%作为缓存容量上限,可通过indices.queries.cache_size更改,这个参数是节点的配置而非索引配置。
第二种缓存被称为分片请求缓存(Shard Request Cache),负责存储分片接收到的查询结果。分片请求缓存不会缓存查询结果的hits字段,也就是具体的文档内容,它一般只缓存聚集查询的相关结果。在默认情况下,分片请求缓存也是开启的,通过索引index.requests.cache.enable参数关闭。另一种关闭该缓存的办法,是在调用_search接口时添加request_cache=false参数。分片请求缓存使用的键是作为查询条件JSON字符串,所以如果查询条件JSON串完全相同,文档的查询几乎可以达到实时。但由于JSON属性之间并没有次序要求,这意味着即使JSON描述的是同一个对象,只要它们属性的次序不同就不能在缓存中命中数据。这一点在使用时需要格外注意。
最后一种缓存就是text类型字段在开启fielddata机制后使用的缓存,它会将text类型字段提取的所有词项全部加载到内存中,以提高使用该字段做排序和聚集运算的效率。由于fielddata是text类型对文档值机制的代替,所以天然就是开启的且不能关闭。但可通过indices.fielddata.cache.size设置这个缓存的容量,默认情况下该缓存没有容量上限。
缓存的引入使得文档检索性能得到了提升,但缓存一般会带来两个主要问题:一是如何保证缓存数据与实际数据的一致;另一个问题是当缓存容量超出时如何清理缓存。数据一致性问题,Elasticsearch是通过让缓存与索引刷新频率保持一致实现的。还记得索引是准实时的吗?索引默认情况下会以每秒一次的频率将文档编入索引,Elasticsearch会在索引更新的同时让缓存也失效,这就保证了索引数据与缓存数据的一致性。缓存数据容量问题则是通过LRU的方式,将最近最少使用的缓存条目清除。同时,Elasticsearch还提供了一个_cache接口用于主动清理缓存。之所以要提供这个接口,是因为Elasticsearch为索引提供了一个主动刷新的接口_refresh,所以最好在主动刷新索引后再主动清理缓存。

_refresh接口

_refresh接口用于主动刷新一个或多个索引,将已经添加的文档编入索引以使它们在检索时可见。在调用该接口时,可以直接调用或与一个或多个索引一起使用,还可以使用_all刷新所有索引,所以以下调用都是正确的:
在这里插入图片描述
事实上,除了使用_refresh接口主动刷新索引外,也可以在操作文档时通过refresh参数刷新索引。

_cache接口

_cache接口用于主动清理缓存,在调用该接口时需要在_cache后附加关键字clear。_cache接口可以清理所有缓存,也可以清理某一索引甚至某一字段的缓存,还可以只清理某一种类型的缓存。例如:
在这里插入图片描述
query、request、fielddata参数分别对应于不同的缓存类型,而fields参数则用于定义清理哪一个字段的缓存。

查看运行状态

除此上述接口以外,Elasticsearch还提供了一组用于查看索引及分片运行情况的接口,包括_stat、_shard_stores和_segments等。由于它们往往在性能分析时使用,所以本小节将它们放在一起讲解。

_stat接口

_stats接口用于查看索引上不同操作的统计数据,可以直接请求也可以与索引名称一起使用。_stats接口返回的统计数据非常多,如果只对其中某一组统计数据感兴趣,可以在_stats接口后附加统计名称。例如以下对_stats接口的调用都是正确的:
在这里插入图片描述
在_stats接口中可以使用的统计名称及它们的含义见表3-4,它们在返回结果中的含义与此相同。
在这里插入图片描述

_shard_stores和_segments接口

_shard_stores接口用于查询索引分片存储情况,而_segments接口则用于查看底层Lucene的分段情况。这两个接口都只能通过GET方法请求,同时都可以针对一个或多个索引,例如:
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/100108.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!