elasticsearch介绍(ElasticSearch 字段类型介绍)
本文目录
ElasticSearch 字段类型介绍
ElasticSearch对字符串拥有两种完全不同的搜索方式. 你可以按照整个文本进行匹配, 即关键词搜索(keyword search), 也可以按单个字符匹配, 即全文搜索(full-text search).
对ElasticSearch稍有了解的人都知道, 前者的字符串被称为not-****yzed字符, 而后者被称作****yzed字符串。
text用于全文搜索的, 而keyword用于关键词搜索.
(1)string
string类型在ElasticSearch 旧版本中使用较多,从ElasticSearch 5.x开始不再支持string,由text和keyword类型替代。
(2)text
当一个字段是要被全文搜索的,比如Email内容、产品描述,应该使用text类型。设置text类型以后,字段内容会被分析,在生成倒排索引以前,字符串会被分析器分成一个一个词项。text类型的字段不用于排序,很少用于聚合。
(3)keyword
keyword类型适用于索引结构化的字段,比如email地址、主机名、状态码和标签。如果字段需要进行过滤(比如查找已发布博客中status属性为published的文章)、排序、聚合。keyword类型的字段只能通过精确值搜索到。
在满足需求的情况下,尽可能选择范围小的数据类型。比如,某个字段的取值最大值不会超过100,那么选择byte类型即可。迄今为止吉尼斯记录的人类的年龄的最大值为134岁,对于年龄字段,short足矣。字段的长度越短,索引和搜索的效率越高。
index分析
store存储
对于float、half_float和scaled_float,-0.0和+0.0是不同的值,使用term查询查找-0.0不会匹配+0.0,同样range查询中上边界是-0.0不会匹配+0.0,下边界是+0.0不会匹配-0.0。
其中scaled_float,比如价格只需要精确到分,price为57.34的字段缩放因子为100,存起来就是5734
优先考虑使用带缩放因子的scaled_float浮点类型。
index分析
store存储
日期类型表示格式可以是以下几种:
ElasticSearch 内部会将日期数据转换为UTC,并存储为milliseconds-since-the-epoch的long型整数。
例子:日期格式数据
逻辑类型(布尔类型)可以接受true/false/”true”/”false”值
二进制字段是指用base64来表示索引中存储的二进制数据,可用来存储二进制形式的数据,例如图像。默认情况下,该类型的字段只存储不索引。二进制类型只支持index_name属性。
在ElasticSearch中,没有专门的数组(Array)数据类型,但是,在默认情况下,任意一个字段都可以包含0或多个值,这意味着每个字段默认都是数组类型,只不过,数组类型的各个元素值的数据类型必须相同。在ElasticSearch中,数组是开箱即用的(out of box),不需要进行任何配置,就可以直接使用。
在同一个数组中,数组元素的数据类型是相同的,ElasticSearch不支持元素为多个数据类型:,常用的数组类型是:
ip类型的字段用于存储IPv4或者IPv6的地址
index分析
store存储
***隐藏网址***
ElasticSearch部署架构和容量规划
前面介绍了ElasticSearch原理和使用相关的内容,在生产环境如何比较科学的进行容量规划、部署、调优、排查问题呢,业界和官方也对相关的问题进行总结,我这边也结合自己的经验对这些使用ElasticSearch经常遇到的问题进行了总结。其中主要包括以下三大模块:
ElasticSearch有多种类型的节点,在前面概述和核心也已经介绍过了。在这里可以重新回顾下。ElasticSearch的部署节点类型如下:
主节点及其候选节点,负责集群状态(cluster state)的管理
配置项:node.master,默认为true
数据节点,负责数据存储及处理客户端请求
配置项:node.data,默认为true
ingest节点,负责数据处理,脚本执行
配置项:node.ingest,默认为true
协调节点
配置项:设置上面三个参数全部为false,那么它就是一个纯协调节点
机器学习节点,收费属于x-pack
在生产环境部署推荐配置整体思路就是:尽量是一个节点只承担一个角色。
因为不同的节点所需要的计算机资源都不一样。职责分离后可以按需扩展互不影响。
资源要求:中高CPU;中高内存;中低磁盘
一般在生产环境中配置3台
一个集群只有1台活跃的主节点,负责分片管理,索引创建,集群管理等操作
资源要求:CPU、内存、磁盘要求都高
资源要求:高配置CPU;中等配置的RAM;低配置的磁盘
资源要求:一般中高CPU;中高内存;低磁盘
协调节点扮演者负载均衡、结果的聚合,在大型的es集群中条件允许可以使用高配的cpu和内存。因为如果客户端发起了深度分页等请求可能会导致oom,这个在之前也有过分析。
注意:
如果和数据节点或者Coordinate节点混合部署,数据节点本来相对有比较大的内存占用。
而Coordinate节点有时候可能会有开销很高的查询导致OOM,这些甚至都有可能影响Master节点,导致集群的不稳定。
搭建一个es集群是由模式可循的。
这是一个基础版的职责分离的部署架构:
但是如果大量的聚合查询等操作,这种架构不太适合了。
当系统中有大量的复杂查询或者聚合时候,我们可增加Coordinating节点,增加查询的性能,这里增加了负载均衡层,通过负载均衡扩展时应用程序无感知。
这样部署部署相互影响,写入多的话,多部署ingetst节点,读的时候聚合查询较多可以多部署协调节点,存储数据量大,可以适当对数据节点进行调优。
我们知道数据有冷热之分,比如写入频繁的日志数据,近期的索引将会频繁写入。es根据数据这些特征引入了hot节点和warm节点。
使用ssd,该节点上的索引不断的有新文档写入和查询,对cpu、io的要求较高。
可以使用HDD,上面的索引不会有写入,查询较少。上面只保存只读索引或者旧索引,使用大容量便宜的机械硬盘。
配置步骤:
针对多机房灾备,ElasticSearch业界有多种不同的通用解决方案:
一个集群中的节点分布在不同的机房
应用程序同时将数据写入两个集群
应用程序先将数据写入消息队列,然后由下游的消费者消费并写入集群
ElasticSearch官方的跨集群复制功能,基于文档操作实现订阅复制
定期将索引备份到外部存储,如hdfs等设备
写请求交给网关,网关实时写入主集群,然后异步写备集群
如下是基于CCR跨集群复制的部署架构,因为篇幅有限,异地多活又是一个很大的话题,其它方案和其细节可以查阅相关资料。
我们知道当es集群的节点数大于索引的分片数时,集群将无法通过水平扩展提升集群的性能。而分片数过多,对于聚合查询以及集群的元数据管理也都有影响。我们可以总结为:
分片数量较多
优点:
缺点:
通常建议一个集群总分片数小于10w。
如何设计分片的数量呢?一个分片保持多大的数据量比较合适呢?
我们需要根据使用场景来设置:
避免使用非常大的分片,因为这会对群集从故障中恢复的能力产生负面影响。而每个分片也会消耗相应的文件句柄,内存和CPU资源,分片太多会互相竞争,影响性能。
主分片数一旦确定就无法更改,只能新建创建并对数据进行重新索引(reindex),虽然reindex会比较耗时,但至少能保证你不会停机。所以我们一定要科学的设计分片数。
这里摘录于官方关于分片大小的建议:
主分片与副本都能处理查询请求,它们的唯一区别在于只有主分片才能处理索引请求。副本对搜索性能非常重要,同时用户也可在任何时候添加或删除副本。额外的副本能给带来更大的容量,更高的呑吐能力及更强的故障恢复能力
3.1.3. 小结
根据实际经验我们稍微总结下:
对于数据量较小(100GB以下)的index
对于数据量较大(100GB以上)的index:
综合考虑整个index的shard数量,如果shard数量(不包括副本)超过50个,就很可能引发拒绝率上升的问题,此时可考虑把该index拆分为多个独立的index,分摊数据量,同时配合routing使用,降低每个查询需要访问的shard数量。
关闭交换分区的方法是:
这里是官方的jvm推荐配置链接:
***隐藏网址***
es的节点提供查询的时候使用较多的内存来存储查询缓存,es的lucene写入到磁盘也会先缓存在内存中,我们开启设计这个es节点时需要根据每个节点的存储数据量来进行判断。这里有一个流行的推荐比例配置:
示例:
有一个业务的数据量预估实际有1T,我们把副本设置1个,那么es中总数据量为2T。
这里31G表示的是jvm设置不超过32g否则不会使用java的指针压缩优化了。
前面也提到过,数据节点推荐使用ssd
可以考虑:
写入的目标在于增大写入的吞吐量,这里主要从两个方面进行优化:
这里可以针对myindex索引优化的示例:
首先有几个原则我们需要清楚:
我们可以通过health相关的api进行查看
我们可以使用profile api来定位慢查询。
在查询条件中设置profile为true的参数,将会显示查询经历的细节。
其结果为:
这里会返回一个shards列表。其中:
主要包含了如下信息:
Profile API让我们清楚地看到查询耗时。提供了有关子查询的详细信息,我们可以清楚地知道在哪个环节查询慢,另外返回的结果中,关于Lucene的详细信息也让我们深入了解到ES是如何执行查询的。
ES记录了两类慢日志:
慢搜索日志
用来记录哪些查询比较慢,每个节点可以设置不同的阈值。
之前我们已经详细分析了ES的搜索由两个阶段组成:
慢搜索日志给出了每个阶段所花费的时间和整个查询内容本身。慢搜索日志可以为查询和取回阶段单独设置以时间为单位的阈值,在定义好每个级别的时间后,通过level决定输出哪个级别的日志。
示例如下
前面参考官方链接:
***隐藏网址***
如果出现节点占用CPU很高,我们需要知道CPU在运行什么任务,一般通过线程堆栈来查看。
这里有两种方式可以查看哪些线程CPU占用率比较高:
这里推荐使用hot_threads api
通过返回的结果可以看到什么线程占用更高,正在做什么操作。更详细的内容可以参考官网:
***隐藏网址***
4.3.2 内存使用率过高
1)缓存类型
首先我们需要了解ES中的缓存类型,缓存主要分成如图所示三大类,如下图所示,一个es节点的内存结构:
Node Query Cache(Filter Context)
Shard Query Cache(Cache Query的结果)
Fielddata Cache
Segments Cache
(segments FST数据的缓存),为了加速查询,FST永驻堆内内存,无法被GC回收。该部分内存无法设置大小,长期占用50%~70%的堆内存,只能通过delete index,close index以及force-merge index释放内存
ES底层存储采用Lucene(搜索引擎),写入时会根据原始数据的内容,分词,然后生成倒排索引。查询时,先通过查询倒排索引找到数据地址(DocID)),再读取原始数据(行存数据、列存数据)。
但由于Lucene会为原始数据中的每个词都生成倒排索引,数据量较大。所以倒排索引对应的倒排表被存放在磁盘上。
这样如果每次查询都直接读取磁盘上的倒排表,再查询目标关键词,会有很多次磁盘IO,严重影响查询性能。为了解磁盘IO问题,Lucene引入排索引的二级索引FST。原理上可以理解为前缀树,加速查询
2)节点的内存查看
3)案例分析
如果节点出现了集群整体响应缓慢,也没有特别多的数据读写。但是发现节点在持续进行Full GC。
常见原因:
Segments个数过多,导致Full GC
我们可以通过查看ElasticSearch的内存分析命令发现:
segments.memory占用很大空间。
解决方案:
Field data cache 过大,导致Full GC
我们可以查看ElasticSearch的内存使用,发现fielddata.memory.size占用很大空间。同时,数据不存在写入和更新,也执行过segments merge。
解决方案:
复杂的嵌套聚合,导致集群Full GC
节点响应缓慢,持续进行Full GC。导出Dump分析。发现内存中有大量 bucket对象,查看日志,发现复杂的嵌套聚合
解决方案:
4)断路器
es有多种断路器,我们可以合理使用,避免不合理操作引发的OOM,每个断路器可以指定内存使用的限制。
关于es的断路器使用可以参考官网文档:
***隐藏网址***
在排查es问题时,我们会使用一些常见的命令来分析cpu、io、网络等问题。常见的命令如下
我们这里按照1s的频率输出磁盘信息
如果想查看和进程关联的信息,可以使用pidstat或者iotop。
例如,下面为iotop的输出结果
sar命令可以诊断操作系统内存相关情况。
PS:我们需要关闭内存交换,内存交换会严重损害性能 。
我们知道,操作系统有内核态和用户态,该命令可以输出相关信息
Recv-Q和Send-Q代表该连接在内核中等待发送和接收的数据长度。
如果改数据太多,可能原因为应用程序处理不及时或者对端的数据接收不及时,比如网络拥塞之类
本片文章先介绍了es的部署架构,回顾了es节点类型以及它们的配置方式,也了解了不同类型对硬件的要求不一样。然后总结了几种不同的架构模式,比如基础部署、读写分离、冷热分离、异地多活等架构模式,在生产环境中一般我们推荐读写分离架构模式,如果可以最好加上冷热分离,不过配置可能稍微复杂点。
对于容量规划与调优,首先要明确存储的数据量和使用场景,推荐内存磁盘比为:搜索类比例(1:16),日志类(1:48);比如2T的总数据,搜索如果要保持良好的性能的话,每个节点31*16=496G。每个节点实际有400G的存储空间。那么2T/400G,则需要5个es存储节点,每个节点分片数多少合适,文中也有介绍。副本分片数需要根据我们的容错需求。我们还总结了集群配置和jvm配置相关的优化。
es的使用优化,我们分别总结了写入和查询的优化。写入是其单次数据量、索引refresh、分词等情况都会影响其吞吐量,我们需要根据实际情况来优化。针对于查询,我们可以使用api工具进行分析,分析慢耗时发在在哪一步。当es集群出现异常时,如cpu过高、内存fullgc、卡顿、变红,我们逐一分析了可能的原因和解决办法,同时也介绍了一些常见的诊断工具和监控api。
我们需要先了解es内部运作的原理,这样才能根据实际情况正确的设置集群参数和数据模型,还需要结合实际工作遇到的问题不断的总结经验,才能用好ElasticSearch。
ElasticSearch 分词器,了解一下
这篇文章主要来介绍下什么是 Analysis ,什么是分词器,以及 ElasticSearch 自带的分词器是怎么工作的,最后会介绍下中文分词是怎么做的。
首先来说下什么是 Analysis:
顾名思义,文本分析就是 把全文本转换成一系列单词(term/token)的过程 ,也叫 分词 。在 ES 中,Analysis 是通过 分词器(Analyzer) 来实现的,可使用 ES 内置的分析器或者按需定制化分析器。
举一个分词简单的例子:比如你输入 Mastering Elasticsearch ,会自动帮你分成两个单词,一个是 mastering ,另一个是 elasticsearch ,可以看出单词也被转化成了小写的。
再简单了解了 Analysis 与 Analyzer 之后,让我们来看下分词器的组成:
分词器是专门处理分词的组件,分词器由以下三部分组成:
同时 Analyzer 三个部分也是有顺序的,从图中可以看出,从上到下依次经过 Character Filters , Tokenizer 以及 Token Filters ,这个顺序比较好理解,一个文本进来肯定要先对文本数据进行处理,再去分词,最后对分词的结果进行过滤。
其中,ES 内置了许多分词器:
接下来会对以上分词器进行讲解,在讲解之前先来看下很有用的 API: _****yzer API :
它可以通过以下三种方式来查看分词器是怎么样工作的:
再了解了 Analyzer API 后,让我们一起看下 ES 内置的分词器:
首先来介绍下 Stamdard Analyzer 分词器:
它是 ES 默认的分词器 ,它会对输入的文本 按词的方式进行切分 ,切分好以后会进行 转小写 处理, 默认的 stopwords 是关闭的 。
下面使用 Kibana 看一下它是怎么样进行工作的,在 Kibana 的开发工具(Dev Tools)中指定 Analyzer 为 standard ,并输入文本 In 2020, Java is the best language in the world. ,然后我们运行一下:
运行结果如下:
可以看出是按照空格、非字母的方式对输入的文本进行了转换,比如对 Java 做了转小写,对一些停用词也没有去掉,比如 in 。
其中 token 为分词结果; start_offset 为起始偏移; end_offset 为结束偏移; position 为分词位置。
下面来看下 Simple Analyzer 分词器:
它只包括了 Lower Case 的 Tokenizer ,它会按照 非字母切分 , 非字母的会被去除 ,最后对切分好的做 转小写 处理,然后接着用刚才的输入文本,分词器换成 ****** 来进行分词,运行结果如下:
从结果中可以看出,数字 2020 被去除掉了,说明非字母的的确会被去除,所有的词也都做了小写转换。
现在,我们来看下 Whitespace Analyzer 分词器:
它非常简单,根据名称也可以看出是 按照空格进行切分 的,下面我们来看下它是怎么样工作的:
可以看出,只是按照空格进行切分, 2020 数字还是在的, Java 的首字母还是大写的, , 还是保留的。
接下来看 Stop Analyzer 分词器:
它由 Lowe Case 的 Tokenizer 和 Stop 的 Token Filters 组成的,相较于刚才提到的 Simple Analyzer ,多了 stop 过滤,stop 就是会把 the , a , is 等修饰词去除,同样让我们看下运行结果:
可以看到 in is the 等词都被 stop filter 过滤掉了。
接下来看下 Keyword Analyzer :
它其实不做分词处理,只是将输入作为 Term 输出,我们来看下运行结果:
我们可以看到,没有对输入文本进行分词,而是直接作为 Term 输出了。
接下来看下 Pattern Analyzer :
它可以通过 正则表达式的方式进行分词 ,默认是用 \W+ 进行分割的,也就是非字母的符合进行切分的,由于运行结果和 Stamdard Analyzer 一样,就不展示了。
ES 为不同国家语言的输入提供了 Language Analyzer 分词器,在里面可以指定不同的语言,我们用 english 进行分词看下:
可以看出 language 被改成了 languag ,同时它也是有 stop 过滤器的,比如 in , is 等词也被去除了。
最后,让我们看下中文分词:
中文分词有特定的难点,不像英文,单词有自然的空格作为分隔,在中文句子中,不能简单地切分成一个个的字,而是需要分成有含义的词,但是在不同的上下文,是有不同的理解的。
比如以下例子:
那么,让我们来看下 ICU Analyzer 分词器,它提供了 Unicode 的支持,更好的支持亚洲语言!
我们先用 standard 来分词,以便于和 ICU 进行对比。
运行结果就不展示了,分词是一个字一个字切分的,明显效果不是很好,接下来用 ICU 进行分词,分词结果如下:
可以看到分成了 各国 , 有 , 企业 , 相继 , 倒闭 ,显然比刚才的效果好了很多。
还有许多中文分词器,在这里列举几个:
IK :
jieba :
THULAC :
大家可以自己安装下,看下它中文分词效果。
本文主要介绍了 ElasticSearch 自带的分词器,学习了使用 _****yzer API 去查看它的分词情况,最后还介绍下中文分词是怎么做的。
更多文章:
linux系统运维面试题(我想找linux运维方面的工作,但是我没有工作经验,面试问我以前工作干什么的时候我该怎么说)
2026年4月13日 13:20
elasticsearch介绍(ElasticSearch 字段类型介绍)
2026年4月13日 13:00
python自带sqlite3(python sqlite 事务)
2026年4月13日 12:20
string转stringbuilder(android开发,String转化成Spanned怎么转化)
2026年4月13日 11:40









