Elasticsearch 索引管理和内核探秘

1. 创建索引,修改索引,删除索引

//创建索引
PUT /my_index
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  },
  "mappings": {
    "my_type": {
      "properties": {
        "my_field": {
          "type": "text"
        }
      }
    }
  }
}

//修改索引
PUT /my_index/_settings
{
    "number_of_replicas": 1
}

//删除索引
DELETE /my_index
DELETE /index_one,index_two
DELETE /index_*
DELETE /_all

2. 默认分词器standard

standard tokenizer:以单词边界进行切分
standard token filter:什么都不做
lowercase token filter:将所有字母转换为小写
stop token filer(默认被禁用):移除停用词,比如a the it等等

修改分词器设置:

启用english停用词token filter

PUT /my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "es_std": {
          "type": "standard",
          "stopwords": "_english_"
        }
      }
    }
  }
}

3.内核--type底层数据结构

type,是一个index中用来区分类似的数据的,类似的数据但可能有不同的fields;
field的value,在底层的lucene中建立索引的时候,全部是opaque bytes类型,不区分类型的,因为lucene是没有type的概念的,在document中,实际上将type作为一个document的field来存储,即_type,es通过_type来进行type的过滤和筛选;
一个index中的多个type,实际上是放在一起存储的,因此一个index下,不能有多个type重名,而类型或者其他设置不同的,因为那样是无法处理的;

最佳实践,将类似结构的type放在一个index下,这些type应该有多个field是相同的;
假如说,你将两个type的field完全不同,放在一个index下,那么就每条数据都至少有一半的field在底层的lucene中是空值,会有严重的性能问题;

//底层存储,一个index下所有的field都会存储,对于不同type下的字段若不存在,则置为空;
{
  "_type": "elactronic_goods",
  "name": "geli kongtiao",
  "price": 1999.0,
  "service_period": "one year",
  "eat_period": ""
}

{
  "_type": "fresh_goods",
  "name": "aozhou dalongxia",
  "price": 199.0,
  "service_period": "",
  "eat_period": "one week"
}

4. 定制dynamic策略和dynamic mapping策略

定制dynamic策略:

true:遇到陌生字段,就进行dynamic mapping;
false:遇到陌生字段,就忽略;
strict:遇到陌生字段,就报错;

dynamic mapping策略:

1)date_detection

默认会按照一定格式识别date,比如yyyy-MM-dd。但是如果某个field先过来一个2017-01-01的值,就会被自动dynamic mapping成date,后面如果再来一个"hello world"之类的值,就会报错。可以手动关闭某个type的date_detection,如果有需要,自己手动指定某个field为date类型。

PUT /my_index/_mapping/my_type
{
    "date_detection": false
}

2)定制自己的dynamic mapping template(type level)

PUT /my_index
{
    "mappings": {
        "my_type": {
            "dynamic_templates": [
                { "en": {
                      "match":              "*_en",
                      "match_mapping_type": "string",
                      "mapping": {
                          "type":           "string",
                          "analyzer":       "english"
                      }
                }}
            ]
}}}
PUT /my_index/my_type/1
{
  "title": "this is my first article"
}
PUT /my_index/my_type/2
{
  "title_en": "this is my first article"
}

title没有匹配到任何的dynamic模板,默认就是standard分词器,不会过滤停用词,is会进入倒排索引,用is来搜索是可以搜索到的
title_en匹配到了dynamic模板,就是english分词器,会过滤停用词,is这种停用词就会被过滤掉,用is来搜索就搜索不到了

3)定制自己的default mapping template(index level)

PUT /my_index
{
    "mappings": {
        "_default_": {
            "_all": { "enabled":  false }
        },
        "blog": {
            "_all": { "enabled":  true  }
        }
    }
}

5. 重建索引

一个field的设置是不能被修改的,如果要修改一个Field,那么应该重新按照新的mapping,建立一个index,然后将数据批量查询出来,重新用bulk api写入index中;批量查询的时候,建议采用scroll api,并且采用多线程并发的方式来reindex数据,每次scoll就查询指定日期的一段数据,交给一个线程即可;

1)一开始,依靠dynamic mapping,插入数据,但是些数据是2017-01-01这种日期格式的,所以title这种field被自动映射为了date类型,实际上它应该是string类型的;

2)当后期向索引中加入string类型的title值的时候,就会报错;如果此时想修改title的类型,是不可能的;

3)唯一的办法是进行reindex,也就是说,重新建立一个索引,将旧索引的数据查询出来,再导入新索引;

4)如果说旧索引的名字,是old_index,新索引的名字是new_index,终端java应用,已经在使用old_index在操作了,难道还要去停止java应用,修改使用的index为new_index,才重新启动java应用吗?这个过程中,就会导致java应用停机,可用性降低;所以说,给java应用一个别名,这个别名是指向旧索引的,java应用先用着,java应用先用goods_index alias来操作,此时实际指向的是旧的my_index;     PUT /my_index/_alias/goods_index

5)新建一个index,调整其title的类型为string;

6)使用scroll api将数据批量查询出来;采用bulk api将scoll查出来的一批数据,批量写入新索引;

POST /_bulk
{ "index":  { "_index": "my_index_new", "_type": "my_type", "_id": "2" }}
{ "title":    "2017-01-02" }

7)反复循环6,查询一批又一批的数据出来,采取bulk api将每一批数据批量写入新索引

8)将goods_index alias切换到my_index_new上去,java应用会直接通过index别名使用新的索引中的数据,java应用程序不需要停机,零提交,高可用;

POST /_aliases
{
    "actions": [
        { "remove": { "index": "my_index", "alias": "goods_index" }},
        { "add":    { "index": "my_index_new", "alias": "goods_index" }}
    ]
}

9)直接通过goods_index别名来查询,GET /goods_index/my_type/_search

5.2 基于alias对client透明切换index
PUT /my_index_v1/_alias/my_index

client对my_index进行操作
reindex操作,完成之后,切换v1到v2
POST /_aliases
{
    "actions": [
        { "remove": { "index": "my_index_v1", "alias": "my_index" }},
        { "add":    { "index": "my_index_v2", "alias": "my_index" }}
    ]
}

6. 倒排索引不可变的好处

(1)不需要锁,提升并发能力,避免锁的问题;
(2)数据不变,一直保存在os cache中,只要cache内存足够;
(3)filter cache一直驻留在内存,因为数据不变;
(4)可以压缩,节省cpu和io开销;

倒排索引不可变的坏处:每次都要重新构建整个索引;

7. document写入的内核级原理

(1)数据写入buffer缓冲和translog日志文件

(2)每隔一秒钟,buffer中的数据被写入新的segment file,并进入os cache,此时segment被打开并供search使用,不立即执行commit;--实现近实时;

数据写入os cache,并被打开供搜索的过程,叫做refresh,默认是每隔1秒refresh一次。也就是说,每隔一秒就会将buffer中的数据写入一个新的index segment file,先写入os cache中。所以,es是近实时的,数据写入到可以被搜索,默认是1秒。

(3)buffer被清空

(4)重复1~3,新的segment不断添加,buffer不断被清空,而translog中的数据不断累加

(5)当translog长度达到一定程度的时候,commit操作发生

(5-1)buffer中的所有数据写入一个新的segment,并写入os cache,打开供使用

(5-2)buffer被清空

(5-3)一个commit ponit被写入磁盘,标明了所有的index segment;会有一个.del文件,标记了哪些segment中的哪些document被标记为deleted了;

(5-4)filesystem cache中的所有index segment file缓存数据,被fsync强行刷到磁盘上

(5-5)现有的translog被清空,创建一个新的translog

//调整刷新的频率
PUT /my_index
{
  "settings": {
    "refresh_interval": "30s"
  }
}

默认会在后台执行segment merge操作,在merge的时候,被标记为deleted的document也会被彻底物理删除;

每次merge操作的执行流程:

(1)选择一些有相似大小的segment,merge成一个大的segment;
(2)将新的segment flush到磁盘上去;
(3)写一个新的commit point,包括了新的segment,并且排除旧的那些segment;
(4)将新的segment打开供搜索;
(5)将旧的segment删除;

POST /my_index/_optimize?max_num_segments=1,尽量不要手动执行,让它自动默认执行;

原文地址:https://www.cnblogs.com/ntbww93/p/9837160.html

时间: 2024-10-08 06:55:59

Elasticsearch 索引管理和内核探秘的相关文章

[Elasticsearch] 索引管理 (一)

索引管理 本文翻译自Elasticsearch官方指南的索引管理(Index Management)一章 我们已经了解了ES是如何在不需要任何复杂的计划和安装就能让我们很容易地开始开发一个新的应用的.但是,用不了多久你就会想要仔细调整索引和搜索过程来更好的适配你的用例. 几乎所有的定制都和索引(Index)以及其中的类型(Type)相关.本章我们就来讨论用于管理索引和类型映射的API,以及最重要的设置. 创建索引 到现在为止,我们已经通过索引一份文档来完成了新索引的创建.这个索引是使用默认的设置

[Elasticsearch] 索引管理 (五) - 默认映射,重索引,索引别名

默认映射(Default Mapping) 一般情况下,索引中的所有类型都会有相似的字段和设置.因此将这些常用设置在_default映射中指定会更加方便,这样就不需要在每次创建新类型的时候都重复设置._default映射的角色是新类型的模板.所有在_default映射之后创建的类型都会包含所有的默认设置,除非显式地在类型映射中进行覆盖. 比如,我们使用_default映射对所有类型禁用_all字段,唯独对blog类型启用它.可以这样实现: PUT /my_index { "mappings&qu

Elasticsearch索引管理

1.判断索引是否存在 IndicesExistsResponse indexResponse = ia.client.admin().indices().prepareExists("blog") .execute().actionGet(); System.out.println(indexResponse.isExists()); 也可以同时判断多个索引是否存在: IndicesExistsResponse indexResponse = ia.client.admin().ind

[Elasticsearch] 索引管理 (四) - 动态映射

动态映射(Dynamic Mapping) 当ES在文档中碰到一个以前没见过的字段时,它会利用动态映射来决定该字段的类型,并自动地对该字段添加映射. 有时这正是需要的行为,但有时不是.你或许不知道在以后你的文档中会添加哪些字段,但是你想要它们能够被自动地索引.或许你只是想要忽略它们.或者 - 尤其当你将ES当做主要的数据存储使用时 - 大概你会希望这些未知的字段会抛出异常来提醒你注意这一问题. 幸运的是,你可以通过dynamic设置来控制这一行为,它能够接受以下的选项: true:默认值.动态添

[Elasticsearch] 索引管理 (三) - 根对象(Root Object)

根对象(Root Object) 映射的最顶层被称为根对象.它包含了: 属性区域(Properties Section),列举了文档中包含的每个字段的映射信息. 各种元数据(Metadata)字段,它们都以_开头,比如_type,_id,_source. 控制用于新字段的动态探测(Dynamic Detection)的设置,如analyzer,dynamic_date_formats和dynamic_templates. 其它的可以用在根对象和object类型中的字段上的设置,如enabled,

[Elasticsearch] 索引管理 (二)

自定义解析器(Custom Analyzers) 虽然ES本身已经提供了一些解析器,但是通过组合字符过滤器(Character Filter),分词器(Tokenizer)以及词条过滤器(Token Filter)来创建你自己的解析器才会显示出其威力. 在解析和解析器中,我们提到过解析器(Analyzer)就是将3种功能打包得到的,它会按照下面的顺序执行: 字符过滤器(Character Filter) 字符过滤器用来在分词前将字符串进行"整理".比如,如果文本是HTML格式,那么它会

一文带您了解 Elasticsearch 中,如何进行索引管理(图文教程)

欢迎关注笔者的公众号: 小哈学Java, 每日推送 Java 领域干货文章,关注即免费无套路附送 100G 海量学习.面试资源哟!! 个人网站: https://www.exception.site/essay/about-elasticsearch-index-manage 在 Elasticsearch 中,索引是一个非常重要的概念,它是具有相同结构的文档集合.类比关系型数据库,比如 Mysql, 你可以把它对标看成和库同级别的概念. 今天小哈将带着大家了解, 在 Elasticsearch

[ElasticSearch]Java API 之 索引管理

ElasticSearch为了便于处理索引管理(Indices administration)请求,提供了 org.elasticsearch.client.IndicesAdminClient接口.通过如下代码从 Client 对象中获得这个接口的实现: IndicesAdminClient indicesAdminClient = client.admin().indices(); IndicesAdminClient定义了好几种prepareXXX()方法作为创建请求的入口点. 1. 索引

elasticsearch系列二:索引详解(快速入门、索引管理、映射详解、索引别名)

一.快速入门 1. 查看集群的健康状况 http://localhost:9200/_cat http://localhost:9200/_cat/health?v 说明:v是用来要求在结果中返回表头 状态值说明 Green - everything is good (cluster is fully functional),即最佳状态Yellow - all data is available but some replicas are not yet allocated (cluster i