《深入理解ElasticSearch》——3.6 控制索引合并

3.6 控制索引合并

读者知道(我们已经在第1章中讨论过),在ElasticSearch中每个索引都会创建一到多个分片以及零到多个副本,也知道这些分片或副本本质上都是Lucene索引,而Lucene索引又基于多个索引段构建(至少一个索引段)。索引文件中绝大部分数据都是只写一次,读多次,而只有用于保存文档删除信息的文件才会被多次更改。在某些时刻,当某种条件满足时,多个索引段会被拷贝合并到一个更大的索引段,而那些旧的索引段会被抛弃并从磁盘中删除,这个操作称为段合并(segment merging)。
也许你会有疑问,为什么非要进行段合并?这是因为:首先,索引段的个数越多,搜索性能越低且耗费内存更多。另外,索引段是不可变的,因而物理上你并不能从中删除信息。也许你碰巧从索引中删除了大量文档,但这些文档只是做了删除标记,物理上并没有被删除。而当段合并发生时,这些标记为删除的文档并没有复制到新的索引段中。如此一来,这减少了最终索引段中的文档数。
频繁的文档更改操作会导致大量的小索引段,从而导致文件句柄打开过多的问题。我们必须要对这种情况有所准备,如修改系统配置,或设置合适的最大文件打开数。
从用户角度来看,段合并可快速概括为如下两个方面:

  • 当多个索引段合并为一个的时候,会减少索引段的数量并提高搜索速度。
  • 同时也会减少索引的容量(文档数),因为在段合并时会移除被标记为已删除的那些文档。

尽管段合并有这些好处,但用户也应该了解到段合并的代价,即主要是I/O操作的代价。在速度较慢的系统中,段合并会显著影响性能。基于这个原因,ElasticSearch允许用户选择段合并策略(merge policy)及存储级节流(store level throttling)。本章后续部分将会讨论段合并策略,而存储级节流则安排在6.2节中讨论。
3.6.1 选择正确的合并策略
尽管段合并是Lucene的责任,ElasticSearch也允许用户配置想用的段合并策略。到目前为止,有三种可用的合并策略:
tiered(默认)

  • log_byte_size
  • log_doc

前面提到的每一种段合并策略都有各自的参数,而这些参数定义了各自的行为特点,并且它们的默认值都是可以覆写的(请阅读后续章节来了解这些参数)。
为了告知ElasticSearch我们想使用的段合并策略,可以将配置文件的index.merge.policy.type字段配置成我们期望的段合并策略类型。例如下面这样:

一旦使用特定的段合并策略创建了索引,它就不能被改变。但是,可以使用索引更新API来改变该段合并策略的参数值。
接下来我们来了解这些不同的段合并策略,以及它们提供的功能,并讨论这些段合并策略的具体配置。
tiered合并策略
这是ElasticSearch的默认选项。它能合并大小相似的索引段,并考虑每层允许的索引段的最大个数。读者需要清楚单次可合并的索引段的个数与每层允许的索引段数的区别。在索引期,该合并策略会计算索引中允许出现的索引段个数,该数值称为阈值(budget)。如果正在构建的索引中的段数超过了阈值,该策略将先对索引段按容量降序排序(这里考虑了被标记为已删除的文档),然后再选择一个成本最低的合并。合并成本的计算方法倾向于回收更多删除文档和产生更小的索引段。
如果某次合并产生的索引段的大小大于index.merge.policy.max_merged_segment参数值,则该合并策略会选择更少的索引段参与合并,使得生成的索引段的大小小于阈值。这意味着,对于有多个分片的索引,默认的index.merge.policy.max_merged_segment则显得过小,会导致大量索引段的创建,从而降低查询速度。用户应该根据自己具体的数据量,观察索引段的状况,不断调整合并策略以满足应用需求。
log byte size合并策略
该策略会不断地以字节数的对数为计算单位,选择多个索引来合并创建新索引。合并过程中,时不时会出现一些较大的索引段,然后又产生出一些小于合并因子(merge factor)的索引段,如此循环往复。你可以想象,时而有一些相同数量级的索引段,其个数会变得比合并因子还少。当碰到一个特别大的索引段时,所有小于该级别的索引段都会被合并。索引中的索引段个数与下次用于计算的字节数的对数成正比。因此,该合并策略能够保持较少的索引段数量并且极小化段索引合并的代价。
log doc合并策略
该策略与log_byte_size合并策略类似,不同的是前者基于索引的字节数计算,而后者基于索引段的文档数计算。以下两种情况中该合并策略表现良好:文档集中的文档大小类似或者你期望参与合并的索引段在文档数方面相当。
3.6.2 合并策略配置
我们现在已经知道索引的段合并策略的工作原理了,只是还缺乏配置方面的相关知识,所以现在就来讨论每种合并策略及其提供的配置选项。请记住,大多数情况下默认选项是够用的,除非有特殊的需求才需要修改。
配置tiered合并策略
当使用tiered合并策略时,可配置以下这些选项:

  • index.merge.policy.expunge_deletes_allowed:默认值为10,该值用于确定被删除文档的百分比,当执行expungeDeletes时,该参数值用于确定索引段是否被合并。
  • index.merge.policy.floor_segment:该参数用于阻止频繁刷新微小索引段。小于该参数值的索引段由索引合并机制处理,并将这些索引段的大小作为该参数值。默认值为2MB。
  • index.merge.policy.max_merge_at_once:该参数确定了索引期单次合并涉及的索引段数量的上限,默认为10。该参数值较大时,也就能允许更多的索引段参与单次合并,只是会消耗更多的I/O资源。
  • index.merge.policy.max_merge_at_once_explicit:该参数确定了索引优化(optimize)操作和expungeDeletes操作能参与的索引段数量的上限,默认值为30。但该值对索引期参与合并的索引段数量的上限没有影响。
  • index.merge.policy.max_merged_segment:该参数默认值为5GB,它确定了索引期单次合并中产生的索引段大小的上限。这是一个近似值,因为合并后产生的索引段的大小是通过累加参与合并的索引段的大小并减去被删除文档的大小而得来的。
  • index.merge.policy.segments_per_tier:该参数确定了每层允许出现的索引段数量的上限。越小的参数值会导致更少的索引段数量,这也意味着更多的合并操作以及更低的索引性能。默认值为10,建议设置为大于等于index.merge.policy.max_merge_at_once,否则你将遇到很多与索引合并以及性能相关的问题。
  • index.reclaim_deletes_weight:该参数值默认为2.0,它确定了索引合并操作中清除被删除文档这个因素的权重。如果该参数设置为0.0,则清除被删除文档对索引合并没有影响。该值越高,则清除较多被删除文档的合并会更受合并策略青睐。
  • index.compund_format:该参数类型为布尔型,它确定了索引是否存储为复合文件格式(compound format),默认值为false。如果设置为true,则Lucene会将所有文件存储在一个文件中。这样设置有时能解决操作系统打开文件处理器过多的问题,但是也会降低索引和搜索的性能。
  • index.merge.async:该参数类型为布尔型,用来确定索引合并是否异步进行。默认为true。
  • index.merge.async_interval:当index.merge.async设置为true(因此合并是异步进行的),该参数值确定了两次合并的时间间隔,默认值为1s。请记住,为了触发真正的索引合并以及索引段数量缩减操作,该参数值应该保持为一个较小值。

配置log byte size合并策略
当采用log_byte_size合并策略时,可配置以下选项:

  • merge_factor:该参数确定了索引期间索引段以多大的频率进行合并。该值越小,搜索的速度越快,消耗的内存也越少,而代价则是更慢的索引速度。如果该值越大,情形则正好相反,即更快的索引速度(因为索引合并更少),搜索速度更慢,消耗的内存更多。该参数默认为10,对于批量索引构建,可以设置较大的值,对于日常索引维护则可采用默认值。
  • min_merge_size:该参数定义了索引段可能的最小容量(段中所有文件的字节数)。如果索引段大小小于该参数值,且merge_factor参数值允许,则进行索引段合并。该参数默认值为1.6MB,它对于避免产生大量小索引段是非常有用的。然而,用户应该记住,该参数值设置为较大值时,将会导致较高的合并成本。
  • max_merge_size:该参数定义了允许参与合并的索引段的最大容量(以字节为单位)。默认情况下,参数不做设置,因而在索引合并时对索引段大小没有限制。
  • maxMergeDocs:该参数定义了参与合并的索引段的最大文档数。默认情况下,参数没有设置,因此当索引合并时,对索引段没有最大文档数的限制。
  • calibrate_size_by_deletes:该参数为布尔值,如果设置为true,则段中被删除文档的大小会用于索引段大小的计算。
  • index.compund_format:该参数为布尔值,它确定了索引文件是否存储为复合文件格式,默认为false。可参考tiered合并策略配置中该选项的解释。
    配置log doc合并策略
    当使用log_doc(文档数对数)合并策略时,可配置以下这些选项:
  • merge_factor:与log_byte_size合并策略中该参数的作用相同,请参考前面的解释。
  • min_merge_docs:该参数定义了最小索引段允许的最小文档数。如果某索引段的文档数低于该参数值,且merge_factor参数允许,就会执行索引合并。该参数默认值为1000,它对于避免产生大量小索引段是非常有用的。但是用户需要记住,将该参数值设置过大会增大索引合并的代价。
  • max_merge_docs:该参数定义了可参与索引合并的索引段的最大文档数。默认情况下,该参数没有设置,因而对参与索引合并的索引段的最大文档数没有限制。
  • calibrate_size_by_deletes:该参数为布尔值,如果设置为true,则段中被删除文档的大小会在计算索引段大小时考虑进去。
  • index.compund_format:该参数为布尔值,它确定了索引文件是否存储为复合文件格式,默认为false。可参考tiered合并策略配置中该选项的解释。

与前面介绍的合并策略类似,上面提及的属性需要以index.merge.policy为前缀。例如,要设置min_merge_docs属性,则应该设置index.merge.policy.min_merge_docs属性。
除此之外,log_doc合并策略支持index.merge.async和index.merge.async_interval属性,就像tiered合并策略那样。
3.6.3 调度
除了可以影响索引合并策略的行为之外,ElasticSearch还允许我们定制合并策略的执行方式。索引合并调度器(scheduler)分为两种,默认的是并发合并调度器ConcurrentMerge-Scheduler。
并发合并调度器
该调度器使用多线程执行索引合并操作,其具体过程是:每次开启一个新线程直到线程数达到上限,当达到线程数上限时,必须开启新线程(因为需要进行新的段合并),那么所有索引操作将被挂起,直到至少一个索引合并操作完成。
为了控制最大线程数,可以通过修改index.merge.scheduler.max_thread_count属性来实现。一般来说,可以按如下公式来计算允许的最大线程数:

如果我们的系统是8核的,那么调度器允许的最大线程数可以设置为4。
顺序合并调度器
该调度器非常简单,它使用同一个线程执行所有的索引合并操作。在执行合并时,该线程的其他文档处理都会被挂起,从而索引操作会延迟进行。
设置合并调度
为了设置特定的索引合并调度器,用户可将index.merge.scheduler.type的属性值设置为concurrent或serial。例如,为了使用并发合并调度器,用户应该如此设置:

如果想使用顺序合并调度器,用户则应该像下面这样设置:

时间: 2024-10-26 18:04:04

《深入理解ElasticSearch》——3.6 控制索引合并的相关文章

《深入理解Elasticsearch(原书第2版)》一导读

前 言 欢迎来到Elasticsearch的世界并阅读本书第2版.通过阅读本书,我们将带领你接触与Elasticsearch紧密相关的各种话题.请注意,本书不是为初学者写的.笔者将本书作为<Elasticsearch Server, Second Edition>的续作和姊妹篇.相对于<Elasticsearch Server>,本书涵盖了很多新知识,不过你偶尔也可以在本书中发现一些引自<Elasticsearch Server>的内容. 本书将探讨与Elasticse

《深入理解ElasticSearch》——导读

前 言 Preface 欢迎来到ElasticSearch的世界.通过阅读本书,我们将带你接触与ElasticSearch紧密相关的各种话题.本书会从介绍Apache Lucene及ElasticSearch的基本概念开始.即使读者熟悉这些知识,简略的介绍也是很有必要的,掌握背景知识对于全面理解集群构建.索引文档.搜索这些操作背后到底发生了什么至关重要. 之后,读者将学习Lucene的评分过程是如何工作的,如何影响评分,以及如何让ElasticSearch选择不同的评分算法.本书也将介绍什么是查

《深入理解ElasticSearch》——第3章 底层索引控制3.1 改变Apache Lucene的评分方式

第3章 底层索引控制 在上一章,我们了解了Apache Lucene如何为文档评分,什么是查询重写,如何利用ElasticSearch 0.90中的新特性,即二次评分来影响搜索返回文档的得分.同时我们也讨论了如何使用单个HTTP请求发送多个查询或准实时读取请求,以及如何对数据进行基于多值字段或嵌套文档的排序.除此之外,还介绍了如何使用数据更新 API以及如何通过使用过滤器优化查询.最后,我们介绍了如何通过使用过滤器和作用域来缩减或增加用于切面计算的文档数量.本章涵盖以下内容: 如何使用不同的评分

《深入理解Elasticsearch(原书第2版)》一第1章Elasticsearch简介1.1 Apache Lucene简介

第1章 Elasticsearch简介 我们希望读者通过阅读本书来获取和拓展关于Elasticsearch的基本知识.假设读者已经知道如何使用Elasticsearch进行单次或批量索引创建,如何发送请求检索感兴趣的文档,如何使用过滤器缩减检索返回文档的数量,以及使用切面/聚合(faceting/aggregation)机制来计算数据的一些统计量.不过,在接触Elasticsearch提供的各种令人激动的功能之前,希望读者能对Apache Lucene有一个快速的了解,因为Elasticsear

《深入理解Elasticsearch(原书第2版)》一1.2 何为Elasticsearch

1.2 何为Elasticsearch 当读者手持本书阅读时,可能已经对Elasticsearch有所了解了,至少已经了解了它的一些核心概念和基本用法.不过,为了全面理解该搜索引擎是如何工作的,我们最好简略地讨论一下它. 也许你已经了解到,Elasticsearch是一个可用于构建搜索应用的成品软件(译者注:区别于Lucene这种中间件).它最早由Shay Banon创建,并于2010年2月发布.之后的几年,Elasticsearch迅速流行开来,成为其他开源和商业解决方案之外的一个重要选择.它

《深入理解Elasticsearch(原书第2版)》一1.1.2 Lucene的总体架构

1.1.2 Lucene的总体架构 尽管我们可以直接探讨Apache Lucene架构的细节,但是有些概念还是需要提前了解的,以便于更好地理解Lucene的架构,它们包括: 文档(document):索引与搜索的主要数据载体,它包含一个或多个字段,存放将要写入索引的或将从索引搜索出来的数据. 字段(field):文档的一个片段,它包括字段的名称和字段的内容两个部分. 词项(term):搜索时的一个单位,代表了文本中的一个词. 词条(token):词项在字段文本中的一次出现,包括词项的文本.开始和

《深入理解Elasticsearch(原书第2版)》一1.2.3 Elasticsearch的工作流程

1.2.3 Elasticsearch的工作流程 本节我们将探索一些关键的Elasticsearch特性,如启动.故障检测.数据索引和查询等.1. 启动过程当Elasticsearch节点启动时,它使用发现(discovery)模块来发现同一个集群中的其他节点(这里的关键是配置文件中的集群名称)并与它们连接.默认情况下,Elasticsearch节点会向网络中发送广播请求,以找到拥有相同集群名称的其他节点.读者可以通过下图的描述来了解相关的处理. 集群中有一个节点被选为主(master)节点.该

《深入理解Elasticsearch(原书第2版)》——第1章 Elasticsearch简介 1.1 Apache Lucene简介

第1章 Elasticsearch简介 我们希望读者通过阅读本书来获取和拓展关于Elasticsearch的基本知识.假设读者已经知道如何使用Elasticsearch进行单次或批量索引创建,如何发送请求检索感兴趣的文档,如何使用过滤器缩减检索返回文档的数量,以及使用切面/聚合(faceting/aggregation)机制来计算数据的一些统计量.不过,在接触Elasticsearch提供的各种令人激动的功能之前,希望读者能对Apache Lucene有一个快速的了解,因为Elasticsear

《深入理解Elasticsearch(原书第2版)》——1.2 何为Elasticsearch

1.2 何为Elasticsearch 当读者手持本书阅读时,可能已经对Elasticsearch有所了解了,至少已经了解了它的一些核心概念和基本用法.不过,为了全面理解该搜索引擎是如何工作的,我们最好简略地讨论一下它. 也许你已经了解到,Elasticsearch是一个可用于构建搜索应用的成品软件(译者注:区别于Lucene这种中间件).它最早由Shay Banon创建,并于2010年2月发布.之后的几年,Elasticsearch迅速流行开来,成为其他开源和商业解决方案之外的一个重要选择.它