Elasticsearch索引;
1 分片和副本
Elasticsearch索引是由一个或多个分片组成的,每个分片包含了文档集的
一部分。而且这些分片也可以有副本,它们是分片的完整副本。在创建索引的过程中,可以规定
应创建的分片及副本的数量。也可以忽略这些信息,并使用全局配置文件(elasticsearch.yml)定
义的默认值,或Elasticsearch内部实现的默认值。如果我们依赖Elasticsearch的默认值,索引结束
时将得到5个分片及1个副本。这意味着什么?简单来说,操作结束时,将有10个Lucene索引分布
在集群中
更多分片使索引能传送到更多服务器,意味着可以处理更多文件,而不会降低性能。
更多分片意味着获取特定文档所需的资源量会减少,因为相较于部署更少分片时,存储
在单个分片中的文件数量更少。
更多分片意味着搜索索引时会面临更多问题,因为必须从更多分片中合并结果,使得查
询的聚合阶段需要更多资源。
更多副本会增强集群系统的容错性,因为当原始分片不可用时,其副本将替代原始分片
发挥作用。只拥有单个副本,集群可能在不丢失数据的情况下遗失分片。当有两个副本
时,即使丢失了原始分片及其中一个副本,一切工作仍可以很好地持续下去。
更多副本意味着查询吞吐量将会增加,因为执行查询可以使用分片或分片的任一副本
2 创建索引
修改索引的自动创建;
新创建索引的设定
映射配置(感觉主要是lucene4.0新特性)
1 类型确定机制
es有一套自己的类型对应机制 通常定义为库,表,Mapping ,字段名称,字段类型
"mappings" : {
"article" : {
"dynamic" : "false",
"properties" : {
"id" : { "type" : "string" },
"content" : { "type" : "string" },
"author" : { "type" : "string" }
}
}
}
2 索引结构映射
模式映射(schema mapping,或简称映射)用于定义索引结构。
你可能还记得,每个索引可以有多种类型,但现在会为了简单起见我们只专注一个类型。
假设想创建一个保存博客帖子数据的posts索引。它可以具有以下结构:
唯一标识符; 名称; 发布日期; 内容。
{
"mappings": {
"post": {
"properties": {
"id": {"type":"long", "store":"yes",
"precision_step":"0" },
"name": {"type":"string", "store":"yes",
"index":"analyzed" },
"published": {"type":"date", "store":"yes",
"precision_step":"0" },
"contents": {"type":"string", "store":"no",
"index":"analyzed" }
}
}
}
}
定义映射涉及类型定义,字段,核心类型,多字段,ip地址类型,分析器
3 不同的相似度模型
允许在文档中使用不同的评分公式。为此,可在name字段和contents字段中
使用BM25相似度模型。这需要扩展我们的字段定义,
并添加similarity属性以及所选择的similarity名称的值。修改映射如下:
{
"mappings" : {
"post" : {
"properties" : {
"id" : { "type" : "long", "store" : "yes",
"precision_step" : "0" },
"name" : { "type" : "string", "store" : "yes",
"index" : "analyzed", "similarity" : "BM25" },
"contents" : { "type" : "string", "store" : "no",
"index" : "analyzed", "similarity" : "BM25" }
}
}
}
}
仅此而已,无需再添加别的。做出上述修改后, Lucene Apache将为字段name和contents
使用BM25相似度模型计算得分因子。
4 信息格式
Lucene4 可以改变索引文件写入的方式,信息格式可在每个字段上设置,就像type或name。
为了把字段配置成默认格式以外的格式,需要添加一个名为postings_format的属性,
将所选择信息格式的名字作为值。如果想在id字段使用pulsing信息格式,
映射将如下所示(pulsing基数越高,字段的重复值就越少,可选性越高。)
{
"mappings" : {
"post" : {
"properties" : {
"id" : { "type" : "long", "store" : "yes",
"precision_step" : "0", "postings_format" : "pulsing" },
"name" : { "type" : "string", "store" : "yes",
"index" : "analyzed" },
"contents" : { "type" : "string", "store" : "no",
"index" : "analyzed" }
}
}
}
}
5 文档值(还待定)
批量索引以提高索引速度
1 批量操作数据结构:
Elasticsearch可以合并多个请求至单个包中,
而这些包可以单个请求的形式传送。
它假定,请求的每一行包含描述操作说明的JSON对象,第二行为JSON对象本身。
可以把第一行视为信息行,第二类为数据行。
唯一的例外是delete操作,它只包含信息行。
{ "index": { "_index": "addr", "_type": "contact", "_id": 1 }}
{ "name": "Fyodor Dostoevsky", "country": "RU" }
{ "delete": { "_index": "addr", "_type": "contact", "_id": 4 }}
2 批量创建索引请求
为了执行批量请求, Elasticsearch提供了_bulk端点,形式可以是/_bulk,也可以是/index_
name/_bulk,甚至是/index_name/type_name/_bulk。第二种和第三种形式定义了索引名称
和类型名称的默认值。可以在请求的信息行中省略这些属性, Elasticsearch将使用默认值
3 使用附加的内部信息扩展索引结构;()
可能很多文档的说明信息 之前是默认不索引的,现在想开启索引
{
"book" : {
"_id" :{
"path": "book_id",
"index": "not_analyzed",
"store" : "no
},
"_type" :{
"store" : "yes"
},
"_all" :{
" enabled" : "false"
},
"_source" : {
"enabled" : false
},
"_index" : {
"enabled" : true
},
"_size" : {
"enabled": true,
"store" : "yes"
},
"_timestamp" : {
"enabled" : true,
"format" : "YYYY"
},
"_ttl" : {
"enabled" : true
},
"properties" : {
.
}
}
}
_id:上述例子在代码中指明希望_id字段不经分析但要编入索引,而且不希望存储。
_type:默认情况下,文档的类型会编入索引,但不会被分析并且不存储
_all支持以下属性
store
term_vector
analyzer
index_analyzer
search_analyzer
_source:默认情况下,_source字段会被开启,当某字段没有存储时,
_source字段可用作高亮功能的数据源。但如果不需要这样的功能,
可禁用_source字段避免存储开销。
为此,需设置_source对象的enabled属性值为false,
或者"_source" : {
"excludes" : [ "author.*" ]
}
用来排除哪些字段,包含哪些字段;
_index:默认情况下, _index字段是禁用的.我们每天创建索引,对索引使用别名,
且想知道返回文档存储在哪个索引中;
_size:默认情况下, _size字段未启用,这使我们能够自动索引_source字段的原始大小
_timestamp:默认情况下,禁用的_timestamp字段允许文档在被索引时存储。
只要添加_timestamp到映射文件并将enabled属性设置为true
_ttl:_ttl字段表示time to live(生存时间),它允许定义文档的生命周期,
周期结束之后文档会被自动删除。默认情况下, _ttl字段是禁用的。
段合并介绍;
1 段:每个索引分为多个“写一次,读多次”(write once and read many time)的段(segment)。
建立索引时,一个段写入磁盘后就不能再更新。
因此,被删除文档的信息存储在一个单独的文件中,但该段自身不被更新。
由于段是无法改变的,因而有关删除的相关信息必须单独存储并动态应用到搜索过程中。
这样做是为了从返回结果中去除已删除的文件;
2 段合并:段合并的处理过程是:底层的Lucene库获取若干段,并在这些段信息的基础上创建一个新的
段。由此产生的段拥有所有存储在原始段中的文档,除了被标记为删除的那些之外。合并操作之
后,源段将从磁盘上删除。这是因为段合并在CPU和I/O的使用方面代价是相当高的,关键是要
适当地控制这个过程被调用的时机和频率
3 段合并的必要性:
你可能会问为何要费心段合并。首先,构成索引的段越多,搜索速度越慢, 需要使用的Lucene
内存也越多。其次,索引使用的磁盘空间和资源,例如文件描述符。
如果从索引中删除许多文档,直到合并发生,则这些文档只是被标记为已删除,
而没有在物理上删除。因而,大多数占用了CPU和内存的文档可能并不存在!
4 合并策略:
可使用index.merge.policy.type属性来设置想使用的合并策略,如下所示:
(值得一提的是,索引创建后将无法再对值进行修改。)
Elasticsearch允许配置以下三种不同的策略。
tiered:这是默认合并策略,合并尺寸大致相似的段,并考虑到每个层(tier)允许的最
大段数量;
log_byte_size:这个合并策略下,随着时间推移,将产生由索引大小的对数构成的索
引,其中存在着一些较大的段以及一些合并因子较小的段等;
log_doc:这个策略类似于log_byte_size合并策略,但根据索引中的文档数而非段的
实际字节数来操作。
5 合并调度器
index.merge.scheduler.type: concurrent
合并调度器指示Elasticsearch合并过程的方式,有如下两种可能。
并发合并调度器:这是默认的合并过程,在独立的线程中执行,定义好的线程数量可以
并行合并。
串行合并调度器:这一合并过程在调用线程(即执行索引的线程)中执行。合并进程会
一直阻塞线程直到合并完成
6 合并因子
它指定了索引过程中段合并的频率。合并因子较小时,搜索的速度更快,占用的内存也更少,但
索引的速度会减慢;合并因子较大时,则索引速度加快,这是因为发生的合并较少,但搜索的速
度变慢,占用的内存也会变大。对于log_byte_size和 log_doc合并策略,可以通过index.
merge.policy.merge_factor参数来设置合并因子。
index.merge.policy.merge_factor: 10
上述例子将合并因子的值设置成10, 10也是默认值。建议在批量索引时设置更高的merge_
factor属性值,普通的索引维护则设置较低的属性值。
调节
在实践中,磁盘I/O操作的数量可能非常大,以致严重影响了整体性
能。这时,调节(throttling)可以改善此情况。事实上,此功能既可用于限制合并的速度,也可
以用于使用数据存储的所有操作。可以在Elasticsearch的配置文件中对调节进行设置
也可以动态使用设置API来设置。调整调节的设置有两个:type和value。
路由介绍
默认情况下, Elasticsearch会在所有索引的分片中均匀地分配文档。然而,这并不总是理想
情况。为了获得文档, Elasticsearch必须查询所有分片并合并结果。然而,如果你可以把数据按
照一定的依据来划分(例如,客户端标识符),就可以使用一个强大的文档和查询分布控制机制:
路由。简而言之,它允许选择用于索引和搜索数据的分片
1 默认索引过程:
在创建索引的过程中,当你发送文档时, Elasticsearch会根据文档的标识符,
选择文档应编入索引的分片。默认情况下, Elasticsearch计算文档标识符的散列值,
以此为基础将文档放置于一个可用的主分片上。接着,这些文档被重新分配至副本
2 默认搜索过程
搜索与索引略有不同,在多数情况下,为了得到感兴趣的数据,你需要查询所有分片。
我们将查询发送到ES的一个节点, Elasticsearch将会根据搜索类型来执行查询。
这通常意味着它首先查询所有节点得到标识符和匹配文档的得分,
接着发送一个内部查询,但仅发送到相关的分片(包含所需文档的分片),
最后获取所需文档来构建响应。
3 路由
路由可以控制文档和查询转发的目的分片。现在,你可能已经猜到了,可以在索引和查询时
都指定路由值。在我们的例子中,索引时使用userId值来设置路由,在搜索时也一样。
对于相同的userId值,计算出的散列值是相同的,
因而特定用户的所有文档将被放置在相同的分片中。
在搜索中使用相同的属性值,则只需搜索单个分片而不是整个索引。
要记住,使用路由时,你仍然应该为与路由值相同的值添加一个过滤器。
这是因为,路由值的数量或许会比索引分片的数量多。
因此,一些不同的属性值可以指向相同的分片以指向相同的分片
4 路由参数
最简单的方法(但并不总是最方便的一个)是使用路由参数来提供路由值。索引或查询时,
你可以添加路由参数到HTTP,或使用你所选择的客户端库来设置
5 路由字段
为每个发送到Elasticsearch的请求指定路由值并不方便。
事实上,在索引过程中, Elasticsearch允许指定一个字段,
用该字段的值作为路由值。这样只需要在查询时提供路由参数。为此,在类
型定义中需要添加以下代码:
{
"mappings" : {
"post" : {
"_routing" : {
"required" : true,
"path" : "userId"
},
"properties" : {
"id" : { "type" : "long", "store" : "yes",
"precision_step" : "0" },
"name" : { "type" : "string", "store" : "yes",
"index" : "analyzed" },
"contents" : { "type" : "string", "store" : "no",
"index" : "analyzed" },
"userId" : { "type" : "long", "store" : "yes",
"precision_step" : "0" }
}
}
}
}