文章目录
-
- 索引分片和lucene关系
- 近实时搜索(refresh)
- flush
- 什么是translog
-
- merge
-
- 集群内部原理
-
- 集群启动流程
-
- 选举主节点
-
- 投票与得票的实现
- 确立Master或加入集群
- 节点失效检测
- 发布集群状态
- 选举集群元信息
- allocation过程
-
- index recovery
-
- ES写流程
-
- create,index,update的区别
- index / bulk基本流程
- 写入异常流程总结
- GET 流程
- Search流程
- 写入速度优化
- 搜索速度优化
- 磁盘使用优化
索引分片和lucene关系
一个Es索引包含很多分片,一个分片是一个Lucene
的索引,它本身就是一个完整的搜索引擎,可以独立执行建立索引和搜索任务。Lucene
索引又由很多分段组成,每个分段都是一个倒排索引。ES每次refresh
都会生成一个新的分段,其中包含若干文档的数据,在每个分段内部,文档的不同字段被单独建立索引。每个字段的值由若干词(Term
)组成,Term
是原文本内容经过分词器处理和语言处理后的最终结果。
近实时搜索(refresh)
在写操作中,首先被写入到内存缓存中,默认每1秒将in-memory index buffer中的文档生成一个新的段并清空原有in-memory index buffer,新写入的段变为可读状态,但是还没有被完全提交。该新的段首先被写入文件系统缓存,保证段文件可以正常被正常打开和读取,后续再进行刷盘操作。由此可以看到,ES并不是写入文档后马上就可以搜索到,而是一个近实时的搜索(默认1s后)
ES的reresh调用的事Lucene的flush,ES的flush调用的Lucene的commit
flush
即使通过每秒refresh实现了近实时搜索,但refresh无法保障数据安全,我们仍然需要经常进行完整提交来确保能从失败中恢复。flush就是一次完全提交的过程,一次完整的提交会将段刷到磁盘,并写入一个包含所有段列表的提交点。Elasticsearch 在启动或重新打开一个索引的过程中使用这个提交点来判断哪些段隶属于当前分片,保证数据的安全。
为此ES增加了一个 translog ,或者叫事务日志,在每一次对 ES的变更操作除写入内存缓存外还会写入到translog中,translog周期性刷盘,保证变更的持久性。
将translog中所有的段进行全量提交并对translog进行截断的操作叫做flush,flush操作期间会做的事项主要有:
- 强制refresh,将内存缓冲区所有文档写入一个新的段,写入到文件系统缓存并将旧的内存缓冲区被清空(refresh)
- 将最新的commit point写入磁盘
- 将文件系统缓存中的段通过fsync进行刷盘
- 删除老的translog,启动新translog
什么是translog
translog就是ES的一个事务日志,当发生一个文档变更操作时,文档不仅会写入到内存缓存区也会同样记录到事务日志中,事务日志保证还没有被刷到磁盘的操作的进行持久化。translog持久化后保证即使意外断电或者ES程序重启,ES首先通过磁盘中最后一次提交点恢复已经落盘的段,然后将该提交点之后的变更操作通过translog进行重放,重构内存中的segment。
translog也可以被用来实时CRUD搜索,当我们通过_id进行查询/更新/删除文档时,ES在检索该文档对应的segment时会优先检查translog中最近一次的变更操作,以便获取到最新版本的文档记录。
translog基本流程
- 一个文档被索引之后,就会被添加到内存缓冲区,并且追加到了translog
- 默认每秒refresh一次,refresh会清空内存缓存,但是不会清空translog
- refresh操作不断发生,更多的文档被添加到内存缓冲区和追加到translog
- translog周期性通过fsync进行刷盘,默认5s,可通过参数index.translog.sync_interval、index.translog.durability控制,保证应用重启后先确认最后记录的commit point,commit point之后的变更操作通过落盘的translog进行重构恢复段
- 默认当translog太大(512MB)时,进行flush操作
merge
每次refresh操作都会生成一个新的segment,随着时间的增长segmengt会越来越多,这就出现一个比较严重的问题是每次search操作必须依次扫描所有的segment,导致查询效率变慢,为了避免该问题es会定期多这个segment进行合并操作。
什么是merge
将refresh产生的多个小segment整合为一个大的segment的操作就叫做merge。同时merge操作会将已经打.del标签的文档从文件系统进行物理删除。merge属于一个后台操作。
在es中每个delete操作其实都是对将要删除的文档打一个.del的标签,同理update操作就是将原文档进行.del打标然后插入新文档,只有merge操作才会将这些已经打标的.del文件真正进行物理删除。
一个大segment的merge操作是很消耗CPU、IO资源的,如果使用不当会影响到本身的serach查询性能。es默认会控制merge进程的资源占用以保证merge期间search具有足够资源。
merge操作相关流程
- refresh操作会相应的产生很多小的segment文件,并刷入到文件系统缓存(此时文件系统中既有已经完全commit的segment也有不完全提交仅searchable的segment)
- es可以对这些零散的小segment文件进行合并(包含完全提交以及searchalbe的segment)
- es会对merge操作后的segment进行一次flush操作,更新磁盘commit point
将merge之后的segment打开保证searchalbe,然后删除merge之前的零散的小segment
集群内部原理
集群节点角色
1. 主节点
- 主节点负责集群层面的相关操作,管理集群变更。
- 通过配置
node.master:true(默认)
是节点具备选举为master的资格,主节点事全局唯一的,将从有资格成为master的节点中进行选举。
- 为了避免网络分区出现多主的情况,配置
discovery.zen.mininum_master_nodes
原则是主节点数过半加一。
2. 数据节点
- 负责保存数据、执行数据相关操作,配置
node.data:true(默认)
来使一个节点成为数据节点。
3.协调节点
- 协调节点将请求转发给保存数据的数据节点。每个数据节点在本地执行请求,并将结果返回协调节点。协调节点收集完数据后,将每个数据节点的结果合并成为单个全局结果,对结果收集和排序的过程可能需要CPU和内存资源。
集群状态
从数据完整性的角度划分,集群状态分为三种:
- Green,所有的主分片和副分片都正常运行。
- Yellow,所有的主分片都运行正常,但不是所有的副分片都正常运行。这意味着存在单点故障的风险。
- Red,有主分片没能正常运行。
每个索引也有上述的三种状态,假设丢失一个副分片,该分片所属的索引和整个集群变为Yellow状态,其他索引认为Green。
集群启动流程
选举主节点
ES的选主算法事基于Bully算法的改进,主要思路是对节点ID排序,取ID最小的节点作为Master,每个节点都运行这个流程。但是会出现选举出的主节点可能不是最新的元数据信息,实际上被分解为两步:先确定唯一的、大家公认的主节点,再想办法把最新的机器元数据复制到选举出的主节点上。
内置的实现称为Zen Discovery
,基于节点ID排序的简单选举算法有三个附加约定条件:
- 参选人数需要过半,达到quorum(多数)后选出了临时的主,为什么是临时的?每个节点运行排序取最小值的算法,结果不一定相同。举个例子,集群中有5台主机,节点ID分别是1、2、3、4、5。当产生网络分区或节点启动速度差异较大时,节点4看到的节点列表是1、2、3、4,选出的节点是2;节点5看到的是2、3、4,选出的是2,结果就不一致了。由此加了第二条限制
- 得票数过半,某节点被选为主节点,必须判断加入它的节点数过半,才确认Master身份,解决第一个问题。
- 当探测节点离开事件时,必须判断当前节点数是否过半。如果达不到quorum,则放弃Master身份,重新加入集群。如果不这么做,则设想一下情况:假设5台机器组成的集群产生网络分区,2台一组,3台一组,产生分区前,Master位于2台其中的一个,此时3台中一组的节点会重新选取Master,产生双主,俗称脑裂。
discovery.zen.minimum_master_nodes
: 最小主节点数,这是防止脑裂、防止数据丢失的及其重要的参数,这个参数的实际作用早已超越了其表面的含义。除了在选主时用于决定"多数",还用于多处重要的判断,至少包含以下时机:
- 触发选主 进入选主的流程之前 ,参选的节点数需要达到法定人数
- 决定Master 选出临时的Master之后,这个临时的Master需要判断加入他的节点达到法定人数,才确认选主成功。
- gateway选举元信息 向有Master资格的节点发起请求,获取元数据,获取的响应数量必须达到法定人数,也就是参与元信息选举的节点数。
- Master发布集群状态 发布成功数量为多数
投票与得票的实现
在ES中,投票就是发送加入集群请求,得票就是申请加入该节点的请求数量
确立Master或加入集群
临时节点Master是本节点:
- 等待足够多的具备Master资格的节点加入本节点(投票数达到法定人数),已完成选举。
- 超时(默认为30s,可配置)后还没有满足数量的join请求,则选举失败,需要进行重新选举。
- 成功后发布新的clusterStatus
如果其他节点被选为Master
- 不再接受其他节点加入请求。
- 向Master发送加入请求,并等待回复,超时时间默认为1分钟,如果遇到异常,则默认重试三次
节点失效检测
节点失效检测会监控节点是否离线,然后处理其中的异常。失效检测是选主流程之后不可获取的步骤,不执行失效检测可能会产生脑裂,在此我们需要启动两种失效探测器:
- 在Master节点,启动NodesFaultDetection,简称NodesFD,定期探测加入集群的节点是否活跃,检查一下当时集群总节点数是否到达法定节点数(过半),如果不足,则放弃Master身份,重新加入集群
- 在非Master节点启动MasterFaultDetection,简称MasterFD,定期探测Master节点是否活跃,如果检测失败,则重新发起选主流程。
发布集群状态
- 什么时刻提交集群任务
- 集群拓扑变化
- 模版、索引map、别名变化
- 索引操作:创建、删除、open、close
- gateway模块发出选举出集群状态
- 集群状态发布过程
发布集群状态是一个分布式事务操作,分布式事务要求实现原子性;要么所有参与者都提交事务,要么都取消事务。ES使用二段提交来实现分布式事务。
两阶段提交过程如下:
- 发布阶段,发布集群状态,等待响应
- 提交阶段:收到的响应数量大于
minimum_master_nodes
数量,发送commit
请求
- 如果超时未提交事务或者超时未收到足够的ack则发布失败,即使只有少数正常,最终也只能接受这个结果。
- 只能保证参与者都提交了事务,不能保证事务在单个节点上提交成功。
- 增量发布原理
- 如果上次发布时节点成功了,则给它准备增量的信息,否则给全量的信息。
选举集群元信息
被选举的Master和集群元信息的新旧程度没有关系,因此它的第一个任务时选举元信息,让各个节点把各自的元信息发过来,根据版本号确定最新的元信息,然后把这个信息广播下去,这样集群的所有节点都有了最新的元信息。
集群元信息的选举包括两个级别:集群级和索引级。不包含哪个shard存在哪个节点这种信息。这种信息以节点存储为准,需要上报,为什么呢?因为读写流程是不经过Master的,Master不知道各shard副本之间的数据差异。
为了集群一致性,参与选举的元信息需要过半,Master发布集群状态成功的规则也是等待发布成功的节点数据过半。
集群元信息选举完毕后,Master发布首次集群状态,然后开始选举shard级元信息。
allocation过程
选举shard级元信息,构建内容路由表,是在allocation模块完成的。在初试阶段,所有的shard都处于unassigned(未分配)状态。ES中通过分配过程决定哪个分片位于哪个节点,构建内容路由表。
1. 选主分片
给每个shard都设置一个UUID,然后在集群级的元信息中记录哪个shard是最新的,因为ES是先写主分片,在由主分片节点转发请求去写副分片,所以主分片节点肯定是最新的,主分片选举是通过集群级元信息中记录了“最新主分片的列表“来确定主分片的;所以,集群重启状态为Yellow,而非Red。
2. 选副分片
主分片选举完成后,从上一个过程中汇总的shard信息中选择一个副本作为副分片。如果汇总信息中不存在,则分配一个全新副本的操作依赖于延迟配置项:
index.unassigned.node_left.delayed_timeout
触发分片的时机
- index增删
- node增删
- 手工reroute
- replica数量改变
- 集群重启
错误检测
主副本定期向其他从副本获取租约,这个过程中可能产生两种情况:
- 如果主副本节点在一定时间内(lease period)未收到从副本节点的租约回复,则主副本节点任务从副本节点异常,想配置管理器回报,将该异常从副本从副本组中移除,同时,它也将自己降级,不再作为主副本节点。
- 如果从副本节点在一定时间内(grace period)未收到主副本节点的租约请求,则认为主副本异常,向配置管理器回报,将主副本从副本组中移除,同时将自己提升为新主,如果存在多个从副本,则哪个从副本先执行成功,哪个从副本就被提升为新主。
只要保证grace period >= lease preiod,则租约机制就可以保证主副本会比任意从副本先感知到租约失效,因此保证了在新主副本产生之前,旧的主分片已经降级,不会产生两个主副本。
index recovery
分配分片成功后进入recovery流程,主分片的recovery不会等待某副本分片成功才开始recovery。它们是独立的流程,只是副本分片的recovery需要主分片恢复完毕才开始。
为什么需要recovery?对于主分片来说,可能有一些数据还没有来得及刷盘;对于副分片来说,一是没刷盘,二是主分片写完了,副分片还没有来得及写,主副分片数据不一致。
1. 主分片recovery
由于每次写操作都会记录事务日志(translog),事务日志中记录了哪种操作,以及相关的数据,因此将最后一次提及(Lucene
的一次提交就是fsync
刷盘的过程)之后的translog中进行重放,建立Lucene
索引,如此完成主分片的recovery
。
2. 副分片recovery
副分片需要恢复与主分片一致,同时,恢复期间允许新的索引操作,在目前6.0版本中,恢复分成两阶段执行。
第一阶段尤其漫长,因为它需要从主分片拉取全量的数据。在ES6.x中,对第一阶段做了优化,标记每个操作,每次写入成功的操作都会分配一个序号,通过对比序列号就可以计算出差异范围,在实现方式上,添加了global checkpoint和local checkpoint,主分片负责维护global checkpoint,代表所有分片已经这个序号的位置,local checkpoint代表当前分片已写入成功的最新位置,恢复时通过对比两个序列号,计算出缺失的数据范围,然后通过translog重放这部分数据。
本地及全局检查点
主分片负责推进全局检查点,它通过跟踪在副分片上完成的操作来完成,一旦它检测到所有副本分片已经超出给定序列号,它将相应更新全局检查点,副分片不会跟踪所有操作,而是维护一个类似全局检查点局部变量,称为本地检查点。
本地检查点也是一个序列号,所有序列号低于它的操作都已在该分片上处理(lucene和translog成功,不一定刷盘),当副分片ACK一个写操作到主分片时,它们也会更新本地检查点,使用本地检查点,主分片节点能够更新全局检查点,然后下一次索引操作时将其发送到所有分片副本。
具体流程:
- 主分片写入一条数据成功后,本地检查点向前推进。
- 主分片将写请求转发到副分片,副分片本地处理成功后,将本地检查点向前推进。
- 主分片收到所有副本分片都处理成功的消息,根据汇报的各副本上的本地检查点更新全局检查点。
- 在下一次索引操作时,主分片节点将全局检查点发送到所有分片副本。
_version
每个文档都有一个版本号(_version),当文档被修改时版本号递增,ES使用这个_version来确保变更以正确顺序执行,如果旧版本的文档在新版本之后到达,则它可以被简单忽略。例如,索引recovery阶段就利用了这个特性。
版本号有主分片生成,在将请求转发给副本分片时将携带此版本号。
版本号的另一个作用时实现乐观锁。如果文档的当前的版本与请求中指定的版本号不同,则请求失败。
ES写流程
create,index,update的区别
在elasticsearch中文档是不可修改的,但是可以通过其它方式来实现文档的更新
内部原理: 删除旧文档,索引新文档在内部,ElasticSearch已将旧文档标记为已删除,并增加一个全新的文档.尽管你不能再对旧版本的文档进行访问,但它并不会立即消失.当继续索引更多的数据,ElasticSearch会在后台清理这些已删除文档.
请求参数「version_type」有两个值,默认internal,请求版本号和存储文档的版本号相同写入,还有一个external类型,请求版本号大于指定版本号才执行写入。
index / bulk基本流程
- 客户端向
NODE1
发送写请求
- NODE1使用文档ID来确定文档属于分片0,通过集群状态中的内容路由信息获知分片0的主分片位于NODE3,因此请求被转发到NODE3上。
- NODE3上的主分片执行写操作。如果写入成功,则它将请求并行转发到NODE1和NODE2的副分片上,等待返回结果。当所有的副分片都报告成功,NODE3将向协调节点报告成功,协调节点再向客户端报告成功。
在2.x版本及之前的版本中,写一致性的默认策略是quorum,即多数的分片,在写入操作时处于可用状态
在5.x版本及6.x版本中,写一致性策略wait_for_active_shards参数,默认情况下,只要主分片活跃状态就可以执行写入操作。wait_for_active_shards只是写入前检查,不保证多个分片副本写入成功。
- 参数校验 : 例如index、type、source不可为空
- 处理pipeline : 数据预处理,可以自定义pipeline和processors实现。
- 自动创建索引: 如果配置为允许自动创建索引(默认允许)
- 合并请求: 若果多个文档的主分片都属于一个,则写请求被合并为一个
- 路由算法: 路由算法就是根据routing和文档id计算目标shardid的过程,shard_num = hash(_routing) % num_primary_shards
- 主分片参数校验:检查是否处于关闭状态
- 延迟执行: 如果需要延迟则放入队列,否则继续下面的流程。
- 判断是否已经发生迁移 如果是,转发请求到迁移的节点
- 检查一致性: 在开始之前检查活跃shard是否足够,不足够则不执行写入,默认1,只要主分片可用就执行写入。
- 写Lucene和事务日志:先写lucene,后写translog,写操作可能会失败,如果先写translog,写入lucene失败,则还需要对translog进行回滚处理。
- flush translog 根据配置的translog flush 策略进行刷盘控制,定时或立即刷盘
- 写副本: 主节点发出多少个Request,就要等待多个Response,无论这些Response是成功还是失败的,直到超时,收到全部Response,给协调节点返回信息,告知哪些成功,哪些失败
- 写副本分片失败:主节点发送shardFaild到Master,这个副本shard将会从同步列表删除,shard将会标记为下线,Master会通过reroute将失败的shard迁移到新的节点,并更新集群状态
写入异常流程总结
- 如果协调节点在路由阶段失败,会等待集群更新,更新完会重试,如果再次失败,依然等待集群更新,知道超时1分钟为止
- 主分片写入是阻塞的,只有主分片成功,才会写副本shard,如果主分片写入失败,则整个请求是失败的。如果有部分副本分片失败,则整个请求则认为是成功。
- 无论主分片还是副分片,当写入一个doc失败,集群不会重试,而是关闭本地的shard,然后向master汇报,删除是以shard为单位的。
GET 流程
- 客户端向协调节点Node1发送GET请求
- NODE1确定文档id来确定文档属于分片0,通过集群状态中的内容路由表信息获知分片0有三个副本数据,位于所有的三个节点中,此时它还可以将请求发送到任意节点,这里它将请求转发到NODE2。
- NODE2将文档返回NODE1,NODE1将文档返回给客户端。
- 如果开始(默认)realTime,5.x版本前从translog中读取,5.X版本后版本为refresh
- update操作会先GET再写,为了保证一致性,update调用GET时将realTime选项设置为true,并且不可配置,因此update操作可能会导致refresh生成新的Lucene段
- 读失败的时候会尝试从别的副本中读取
优先级策略只是将匹配到优先级的节点放到了目标节点列表的前面。
mget请求,如果部分失败,则不影响其他结果,检索失败的doc会在回复消息中标出。
Search流程
在协调节点中,搜索任务分为两个阶段query then fetch
。真正执行搜索任务的节点被称为数据节点。
例如,有5个分片,查询返回前10个匹配最高的文档,那么每个分片都查询出当前分片的TOP10,协调节点将5*10=50的结果再次排序,返回最终TOP10的结果返回给客户端。
- Query阶段
- 客户端发送发送search请求到NODE3
- NODE3将查询请求转发到索引的每个主分片或副分片中
- 每个分片在本地执行查询,并使用本地Term/Document Frequency信息进行打分,添加结果大小为from + size 的本地有序优先队列中(优先级队列大小为from+size)。
- 每个分片返回各自优先队列所有文档ID和排序值给协调节点,协调节点合并这些值到自己的优先队列中,产生一个全局排序后的列表。
- Fetch阶段
Query阶段知道了要取哪些数据,但是并没有取具体数据,这就是Fetch阶段要做的。为了避免在协调节点中创建的number_of_shards * (from + size)队列过大,应该尽量控制分页深度。
- 协调节点向相关NODE发送GET请求,是根据文档id获取。
- 分片所在节点向协调节点返回数据。
- 协调节点等待所有文档被取的,然后返回给客户端。
Elasticsearch之SearchScroll原理剖析和性能及稳定性优化
ES系列十二、ES的scroll Api及分页实例
写入速度优化
- translog flush 间隔调整,降低磁盘io
- 索引刷新间隔refresh_interval,默认为1s,这意味着数据写入1s后就可以被搜索到,每次索引refresh会产生一个新的lucene段,这会导致频繁的segment merge行为,如果不需要这么高的实时搜索性,应该降低索引的refresh周期。
- 段合并优化
- 当多个索引段合并为一个的时候,会减少索引段的数量并提高搜索速度
- 段合并发送时,这些标记为删除的文档并没有被复制到新的索引段中
- es 段合并的原理和作用
- 调整index buffer大小,当缓冲满时会刷入磁盘,生成一个新的segment,这是除了refresh_interval刷新索引外,另一个生成segment的机会
- 使用bulk请求
- 注意bulk请求的整体字节数不要太大,太大的请求可能会给集群带来内存压力
- bulk线程池和队列,创建索引属于计算行密集型任务,线程池默认为CPU+1,避免过多的线程池切换,可以适当增加队列大小,但要限制大小,过大会引起GC压力,导致FULL GC的频繁发生
- 并发请求要注意ES的bulk队列已满的时候,客户端会收到429错误(TOO_MANY_REQUESTS)。
- 调整mappings
- 减少字段数量,对于不需要建立索引的字段,不写入ES
- 将不需要建立索引的字段index属性设置为not_analyzed或no。对分段不分词,或者不索引,可以减少很多运算操作。
- 减少字段长度
- 使用不同的分析器,不同的分析器在索引过程中运算复杂度也有较大的差异
- 调整_source字段
- _source字段用于存储doc原始数据,对于部分不需要存储的字段,可以通过includes或者excludes过滤,或者将_source禁用,一般用于索引和数据的分离。
- 禁用_all字段
- 由于需要从其他的全部字段复制所有的值,导致占用_all字段占用非常大的空间。
- _all字段有自己的分析器,在进行某些查询时,结果有可能不符合预期。
- 对Analyzed的字段禁用Norms,不需要评分,可以将其禁用
搜索速度优化
- 为文件系统cache预留足够的的内存,命中cache可以降低对磁盘的直接访问频率。
- 使用更快的硬件,比如SSD
- 文档模型,文档应该合理建模特别避免join操作,嵌套使查询慢几倍,父子关系可能使查询慢数百倍。
- 字段映射,例如,一些标识符将它们映射为keyword可能比integer或者long更好。
- 避免使用脚本 一般来说,应该避免使用脚本
- 为只读索引执行force-merge,为不再更新的只读索引执行force merge,将Lucene索引合并为单个分段,可以提升查询速度,当一个Lucene索引存在多个分段时,每个分段会单独执行搜索再将结果合并,将只读索引强制合并为一个Lucene分段不仅可以优化搜索过程,对索引恢复速度也有好处。
- 调节搜索请求中的batched_reduce_size,该字段是搜索请求中的一个参数,默认情况下,聚合操作在协调节点需要等所有的分片都取回结果后才执行,使用batched_reduce_size参数可以不等待全部分片返回结果,而是在指定数量的分片返回结果之后就可以先处理一部分,这样就可以避免协调节点在等待全部结果的过程中使用大量内存,避免极端情况下可能导致OOM,该字段默认值默认为512。
- 限制搜索请求的分片数,一个搜索请求涉及的分片数越多,协调节点的CPU和内存压力就越大。默认情况下,ES会拒绝超过1000个分片的搜索请求。
磁盘使用优化
- 元数据字段
- _source: 原始的JSON 文档数据,如果确定没有一下情况,可以禁用_source,可以降低占用量约30%
- update、update_by_query、reindex
- 高亮搜索
- 重建索引
- 调试聚合查询功能,需要对比原始数据。
- _all: 包含了所有其他字段值,允许在搜索时不指定特定的字段名,从ES6.0中该字段开始被禁用
- 索引映射参数
- index:控制字段是否被索引,默认为true,未被索引的字段不会被查询到,但可以聚合,除非禁用doc_values。
- doc values: 默认情况下,大多数字段都被索引,这使得它们可以搜索,倒排索引根据term找到文档列表。doc_values是在磁盘列式存储的,几乎所有字段类型都支持doc_values,除了text,doc_values默认启用。如果确定不需要对字段进行排序或者聚合,或者从脚本访问字段值,则可以禁用doc value以节省磁盘空间。占用空间可降低10%
- store: 默认情况下,字段值会被索引使它们能搜索,但它们不会被存储,意味着可以通过这个字段查询,但不能取回它的原始值。Elasticsearch中的store field跟non-store field的区别
-
不要使用默认动态字符串映射,默认的动态字符串映射会把字符串类型字段同时索引为text和keyword,可以指定字符串映射为text或者keyword。
-
使用best_compression,默认情况下,它们都是被压缩存储的,默认的压缩为LZ4,可以通过best_compression来执行压缩比更高的算法,比如DEFLATE。占用空降可降低15%-25%。
-
fource merge,通常,我们将分段合并成一个单个的分段,max_num_segments=1
-
shrink index,减少索引的分片数量
-
数值类型长度够用就好,整形依次为byte、short、integer、或long、浮点可以选择scaled_float、float、double、half_float,每个数据类型的长度是不同的,为业务选择够用的最小数据类型,可以节省磁盘空间。 Elasticsearch的数据类型
-
Elasticsearch冷热分离原理和实践