ES优化里的一些 "黑话"

498 阅读11分钟

ES使用时,怎么优化,这是面试超高频的一个问题,可以从以下几个方面回答:

设计阶段调优
1、根据业务增量需求,采取基于日期模板创建索引,通过roll over API滚动索引;

在ES中,采用基于日期模板创建索引是为了优化数据的存储和查询性能,并且也能更好地满足实际业务需求。具体来说,基于日期模板创建索引可以将数据以时间为基准进行分片、分散到不同的索引中,从而使每个索引的数据量更小,查询性能更高。在实际应用中,大多数数据都是按照时间顺序产生的,如果将数据按时间分割成不同的索引,就可以充分发挥ES水平扩展的优势,让每个索引处理相同数量的数据,从而提高ES集群的整体性能。此外,基于日期模板创建索引,还能够更好地满足实际业务需求,例如:按天、按周、按月或按年等时间单位进行索引划分,针对不同的时间段采用不同的数据存储策略,使得数据检索更加便捷、高效。同时,这种索引划分方法还可以方便地进行数据的删除或者迁移,减小数据存储空间,降低存储成本。--- Elasticsearch中的Scroll API是一种查询API,它主要用于处理大量数据的查询。在传统的查询方式中,一次查询只能返回一定数量的结果,当我们需要查询的数据量很大时,必须不断地发送多次请求来获取所有的数据。而使用Scroll API就可以将所有的满足条件的数据都缓存在内存中,当我们需要分批次处理这些数据时,可以通过滚动游标的方式,逐步地获取所有的查询结果,避免了因为数据量太大而无法一次性获取的问题。

2、使用别名进行索引管理;

在ES中,使用别名进行索引管理是一种非常实用的方式。其主要原因有以下几点: 第一,别名可以为索引提供一个简洁、易于记忆的名称。在实际应用中,可能会存在大量的索引,如果每个索引都使用较长的名称,则不仅容易出错,而且不方便用户使用。使用别名可以为不同的索引分配一个简洁、易于管理的名称,方便用户进行操作和查询。 第二,别名可以方便地替换或删除索引。在ES中,可能会存在不同的索引版本或者索引结构,如果使用具体的索引名称进行操作,可能会出现一些管理问题。使用别名可以有效地解决这些问题,因为别名是一个虚拟的名称,可以指向不同的实际索引。这样,当需要替换或者删除索引时,只需要重新设置别名即可,不需要更改索引的名称,避免了复杂的管理问题。 第三,别名可以实现索引的版本控制。ES中的别名可以指向多个索引,这样就可以实现索引的版本控制。例如:指向最新版本的索引,或者指向历史版本的索引。这使得用户可以方便地查找之前的数据,并且可以随时回退到之前的版本。 第四,别名还可以提高ES集群的高可用性和灵活性。当一个节点发生故障或者维护时,可以将别名指向其他健康的节点,实现无缝切换,从而提高集群的可用性。此外,使用别名还可以实现索引的动态增减,避免了对索引和数据的重新索引,使得数据管理更加灵活。

3、每天凌晨定时对索引做force_merge 操作,以释放空间;

在Elasticsearch中,每个索引都由一个或多个分片(shard)组成,每个分片都是一个独立的Lucene索引。当索引中的删除或更新操作达到一定的数量之后,Lucene索引中就会产生大量的碎片(fragment),这些碎片会占用大量的磁盘空间,并影响搜索性能。为了优化索引的性能,我们需要定期对索引进行合并,在Lucene中,这个过程称为force merge。定时对索引进行force merge,并不是将所有碎片都合并成一个大的段,而是选择合适的碎片集合进行合并,生成更大的段,一般在晚上或流量较小时运行,避免对搜索性能产生影响。通过定时合并索引,可以释放一些磁盘空间,并提高搜索性能。对于使用Doc Values功能的字段,即使不出现文档的添加或者修改,也会随着索引的存储时间增长,产生越来越多的碎片,影响性能,需要定期进行force merge,这也是一个保持索引健康的好习惯。

4、采取冷热分离机制,热数据存储到SSD,提高检索效率;冷数据定期进行 shrink操作,以缩减存储;

在Elasticsearch中,通过合并碎片(merge)可以减小索引占用的磁盘空间,但是经常合并索引会影响搜索性能,因为每次合并都需要消耗一定的CPU和I/O资源。在某些情况下,使用shrink操作可以达到与merge相同的效果,并且减少搜索性能的影响。shrink操作是一种将一个索引缩小为更少主分片(primary shard)和副本分片(replica shard)的操作。这个操作需要创建一个新的索引,因为每个索引一旦创建,其主分片的数目就固定不变了。在新创建的索引中,新的主分片数目会比原来的主分片数目少,并将原来的所有分片合并到新创建的索引中,从而达到减小索引的大小的效果。冷数据定期进行shrink操作,可以将不常使用的数据从原先大的索引中剥离出来,减小磁盘空间的占用,提高磁盘的使用率,同时也减轻了Elasticsearch进行search操作时的负载。另外,由于缩小后的索引分片变少,对于索引的备份和恢复操作也会更加高效。需要注意的是,shrink操作只对主分片数量大于1的索引有效,并且要求分片数必须能被缩小后的主分片数整除。否则,shrink操作会失败。总之,通过定期运行shrink操作,可以释放一些磁盘空间,提高索引的使用率,减轻Elasticsearch的search操作负载,从而提高整个系统的性能。

5、采取 curator 进行索引的生命周期管理;

Curator是一个Elasticsearch的Python库,用于管理Elasticsearch中的索引和快照,可以用于自动化管理索引的创建、删除、合并、优化等操作,也可以设置索引生命周期,达到自动删除或者归档索引的目的。使用Curator进行索引的生命周期管理,可以帮助管理索引占用的磁盘空间,达到上限时自动删除或归档一些旧的或已经不再使用的索引,避免磁盘空间占满导致系统崩溃。另外,通过Curator对索引进行定期的优化和合并操作可以提高搜索性能和减小索引的数据碎片。Curator的另一个优点是,可以通过配置文件进行索引的生命周期管理,一旦配置完成,就可以稳定的运行,减少了手动维护的成本。并且,Curator提供了检查索引状态并在状态满足规定的条件时执行管理指令的功能,使得管理和自动化运维更加方便和高效。

6、仅针对需要分词的字段,合理的设置分词器;
7、Mapping阶段充分结合各个字段的属性,是否需要检索、是否需要存储等。
写入优化
1、写入前副本数设置为 0;
2、写入前关闭refresh_interval设置为-1,禁用刷新机制;

在Elasticsearch中,每次写入操作都会触发refresh操作,也就是将新加入的文档立刻刷新到内存中,并让新加入的文档在搜索结果中可见。这个操作会对搜索性能产生影响,尤其是在大量写入操作时,频繁触发refresh机制会影响写入性能。当关闭refresh机制时,Elasticsearch会暂停将写入的文档直接刷新到内存中,而是在后续的一段时间里(或达到了一定数据量)再一次性刷新。因此,当你需要向Elasticsearch写入大量数据时,关闭refresh机制会加速写入速度,提高写入性能。但是,在某些情况下,禁用refresh机制会使Elasticsearch中存在数据一段时间,但是这些数据在搜索结果中是不可见的。因此,在关闭refresh机制之前,需要仔细考虑场景和需求,确保在可接受的时间范围内将写入的数据刷新到内存中,并且确保用户可以搜索到这些数据。

3、写入过程中:采取bulk批量写入;
4、写入后恢复副本数和刷新间隔;
5、尽量使用自动生成的id。
查询优化
1、禁用wildcard;
2、禁用批量terms(成百上千的场景);

在Elasticsearch中,批量terms查询是一种同时查询多个文档的方式,它可以通过一次请求查询多个Id、多个关键字或者多个短语,通常用于性能优化。但是,在查询大量数据时,如果同时使用批量terms查询,会对Elasticsearch查询的性能产生非常大的影响,可能导致查询变得非常缓慢,甚至无法完成查询。因此,建议禁用批量terms查询,以防止性能下降或查询失败。在Elasticsearch的官方文档中,也建议尽可能避免大量使用批量terms查询,特别是在高并发的查询场景下,因为批量terms查询会带来以下缺点:1.会导致大量内存开销和难以接受的CPU消耗。每次使用批量terms查询时,Elasticsearch需要检查查询是否命中索引中符合条件的文档,这个过程会消耗大量的CPU资源,并在内存中保存大量的数据,因此会导致性能下降。2.会影响搜索的准确性。批量terms查询将多个条件作为一个查询请求发送给Elasticsearch,如果其中一个条件查询失败,整个请求就会失败,从而导致整个查询失败,这会影响搜索结果的准确性和稳定性。因此,在实际使用Elasticsearch的过程中,尽可能避免使用批量terms查询以防止查询的性能下降或者查询失败。如果需要进行批量查询操作,可以考虑使用scroll和bulk等其他的查询方式。

3、充分利用倒排索引机制,能keyword类型尽量keyword;
4、数据量大时候,可以先基于时间敲定索引再检索;

在ES中,为了优化查询性能和准确性,通常可以考虑先根据时间范围来确定需要查询的索引,然后再进行检索。这种方法被称为“时间窗口查询”。时间窗口查询是因为在大数据量情况下,ES的检索性能会受到很大的影响,可能查询时间会非常长而且查询负载很高。如果将所有数据都放在一个索引中,不仅会导致索引文件变得非常大,而且每次查询都需要检索整个索引。这样会导致查询性能下降,甚至会对系统的稳定性产生影响。因此,为了优化查询性能,可以将数据根据时间范围分散到不同的索引中,比如:按日、按周、按月或者按年划分索引。这样每次查询时,可以根据时间窗口范围来确定需要查询的索引,只需要检索对应时间段的索引,而不是整个索引,从而优化查询性能。对于大数据量的查询,时间窗口查询可以让查询变得更快,更准确,并且也可以更好地控制查询负载,避免对整个ES集群造成过大的压力,保证系统的稳定性。因此,时间窗口查询在ES中被广泛应用,是一个非常有效的查询优化手段。

5、设置合理的路由机制。