作者介绍李萌(ynuosoft),Elastic-stack产品深度用户,ES认证工程师,2012年开始接触Elasticsearch,并拥有丰富的Elastic-Stack开发、架构、运维等经验,经验丰富,实践过多种Elasticsearch项目,最暴力的大数据分析应用,最复杂的业务系统应用;业余时间为企业提供Elastic-stack咨询培训和调优实施。前言Elasticsearch,中文名直译为elasticsearch。不仅支持单索引内shard级别的elasticsearch,也支持cross-index外围的shard弹性搜索。与其他分布式数据产品相比,这一特点更加鲜明,代表了Elastic集群架构设计的优势。本文将从以下几个方面进行探讨:为什么需要跨索引查询?交叉索引查询有哪些经典应用场景?交叉索引查询的技术原理是什么?交叉索引查询有哪些注意事项?一张索引查询效果图为什么需要跨索引查询技术限制Elasticsearch索引本身也有一些索引限制,最容易被很多新手忽略或者乱用。弹性索引数据量有大小限制;官方建议单个分片的数据容量不超过50GB,合理范围在20GB到40GB之间;一般很难达到,基本可以忽略。底层原理可以参考源码或其他;索引分片过多,分布式资源消耗越大,查询响应越慢。基于以上限制,索引在创建前需要根据业务场景进行预估,设置合理的分片数量,既不能太多也不能太少。技术便利性在基于关系型数据库的应用场景中,数据量过大,一般采用分库分表的策略。查询数据时,基于第三方中间件,有很多限制;在基于NoSQL的应用场景中,比如MongoDB,数据量过大,会利用数据产品本身提供的分片特性,查询数据会基于自身的路由机制。不管是分库分表还是分片,都只是解决一维数据的存储和查询,二维数据无法使用。比如电商订单系统场景,数据库采用多库多表拆分。一旦容量超过预期设计,就需要进行第二次拆分,继续分库分表;MongoDB采用多分片拆分。一旦容量超过预期设计,就需要继续扩容分片节点。Elasticsearch不需要以上内容。它提供了一种二维分裂的方法。第一维使用多索引命名拆分,第二维使用索引多分片。对于查询,可以灵活匹配索引,一次指定一个。索引,也可以一次指定多个索引。图:ES查询图+多索引+多分片图跨索引查询应用场景在IT应用中,除了技术本身的限制外,大部分问题都是由耦合引起的。“高内聚,低耦合”一直是我们IT从业者的座右铭。应用系统耦合成为一个单一的应用,进而延伸出微服务架构的概念。同样的数据耦合,我们也需要基于某个维度的微服务,或垂直或水平或纵横混合。业务系统给出了一些业务场景的例子,实时数据和历史数据的存储和查询问题,假设日均数据量超过1000万,那么月数超过3亿,年数将超过36亿。如果使用Elasticsearch存储,可以按月/季/年创建索引,这样实时数据更新只会影响当前索引,不会影响历史索引;查询也是如此,根据查询条件指定索引名称,按需扫描查询,不用每次都扫描所有数据。这比传统的基于数据的产品要灵活得多。图解:实时数据和历史数据业务场景大数据Elasticsearch在大数据应用场景中非常流行,已经成为大数据平台对外提供查询结果的标配。大数据平台需要定期对数据进行计算,并将计算结果批量写入Elasticsearch,供业务系统查询。由于一些业务规则的设置,Elasticsearch原有的索引数据必须全部删除并重写。这种操作非常频繁。对于大数据平台来说,每次全量计算的成本是非常高的。对于Elasticsearch平台来说,超大索引数据的频繁删除和重构,成本也非常高。基于以上,采用多索引的方式,比如按月进行拆解,根据需要删除的月份来索引数据。同样的问题,业务系统在查询的时候,可以很灵活的指定需要的月指标数据,保证了存储和查询的平衡。图解:大数据平台向Elastic平台写入数据示意图日志Elasticsearch非常擅长处理这种日志场景,大名鼎鼎的ELK组合由此诞生。比如一个大中型业务系统,每天的日志量在几十TB/几百TB。索引是按天或按小时或更小的粒度创建的。通常,查询日志只会查询最近的日志,而查询过去很长时间的日志。偶尔需要多查询几次,甚至删除。所以对于这种场景,Elasticsearch的交叉索引查询非常方便,编程也非常简单。交叉索引查询应用方式Elasticsearch交叉索引查询方式可根据业务场景灵活选择。下面介绍几种类型:直接类型明确指定多个索引名称。这种方式一般用于非常精确的查询场景,方便查询索引范围。考虑到性能平衡,如果索引不存在,会报错,如下:index_01,index_02GET/index_01,index_02/_search{"query":{"match":{"test":"data"}}}fuzzy类型不限制死索引Name,这种方式一般使用通配符,不需要判断索引是否存在,支持前匹配、后匹配、前后匹配,如下:index_*匹配所有indexeswiththesameprefixGET/index_*/_search{"query":{"match":{"test":"data"}}}计算出的索引名由计算表达式指定,类似于正则表达式,也可以同时指定多个索引,如下:logstash-{now/d}表示当前日期#Index名称如:index-2024.03.22#GET/
