elasticsearch(19) 聚合操作的一些坑

1.如果某个field进行了分词,那么就没有正排索引,不能进行聚合操作,可以使用两种方式解决

a.利用keyword

b.建立mapping时把fielddata=true 这时候会建立正排索引

 

 

POST /test_index/_mapping/my_type
{
  "properties": {
    "my_field": {
      "type": "text",
      "fielddata": { 
        "filter": {
          "frequency": { 
            "min":              0.01, 
            "min_segment_size": 500  
          }
        }
      }
    }
  }
}

min:仅仅加载至少在1%的doc中出现过的term对应的fielddata

比如说某个值,hello,总共有1000个doc,hello必须在10个doc中出现,那么这个hello对应的fielddata才会加载到内存中来

min_segment_size:少于500 doc的segment不加载fielddata

加载fielddata的时候,也是按照segment去进行加载的,某个segment里面的doc数量少于500个,那么这个segment的fielddata就不加载
 

 

1、fielddata核心原理

fielddata加载到内存的过程是lazy加载的,对一个analzyed field执行聚合时,才会加载,而且是field-level加载的
一个index的一个field,所有doc都会被加载,而不是少数doc
不是index-time创建,是query-time创建

2、fielddata内存限制

indices.fielddata.cache.size: 20%,超出限制,清除内存已有fielddata数据
fielddata占用的内存超出了这个比例的限制,那么就清除掉内存中已有的fielddata数据
默认无限制,限制内存使用,但是会导致频繁evict和reload,大量IO性能损耗,以及内存碎片和gc

3、监控fielddata内存使用

GET /_stats/fielddata?fields=*
GET /_nodes/stats/indices/fielddata?fields=*
GET /_nodes/stats/indices/fielddata?level=indices&fields=*

4、circuit breaker

如果一次query load的feilddata超过总内存,就会oom --> 内存溢出

circuit breaker会估算query要加载的fielddata大小,如果超出总内存,就短路,query直接失败

indices.breaker.fielddata.limit:fielddata的内存限制,默认60%
indices.breaker.request.limit:执行聚合的内存限制,默认40%
indices.breaker.total.limit:综合上面两个,限制在70%以内

 

 

<think>我们正在处理用户关于Elasticsearch7中terms聚合分区实现的问题。根据引用[3],我们看到了一个使用分区过滤(partitionfilter)的例子,它是在terms聚合中使用include参数,并指定partition和num_partitions来实现的。在Elasticsearch中,terms聚合可以通过设置include参数来指定只包含某些桶,而分区过滤是其中一种方式。它允许我们将整个数据集合分成多个分区,然后每次只处理一个分区。这对于大数据集非常有用,因为可以避免内存溢出,并且可以并行处理多个分区。具体实现方法如下(基于引用[3]的示例):在terms聚合中,使用`include`参数,并设置`partition`(当前分区的编号,从0开始)和`num_partitions`(总分区数)。这样,每个分区只处理数据的一个子集。示例代码:```jsonGET /_search{"size":0,"aggs": {"expired_sessions": {"terms":{"field": "account_id","include": {"partition":0,//当前处理的分区编号,从0开始"num_partitions":20//总分区数},"size":10000,//每个分区返回的桶数"order": {"last_access": "asc"//按照子聚合last_access排序}},"aggs":{"last_access":{"max": {"field":"access_date"}}}}}} ```在这个例子中,我们将数据分成20个分区(num_partitions=20),然后处理第一个分区(partition=0)。通过改变partition的值(0到19),我们可以分别处理每个分区。注意:1.分区过滤是通过哈希函数将字段值映射到不同的分区,因此同一个字段值总是落在同一个分区。但是,不同的字段值可能会被映射到同一个分区(哈希冲突),但这是均匀分布的。2.使用分区后,每个terms聚合只处理一个分区的数据,因此返回的桶数最多为size指定的数量(这里为10000)。如果某个分区的数据量很大,可能需要调整size参数。3.分区的数量(num_partitions)需要根据数据量和硬件资源来设定。分区数越多,每个分区的数据量越小,但需要更多次查询来覆盖所有数据。因此,在Elasticsearch7中实现terms聚合的分区处理,就是利用terms聚合中的include参数,结合partition和num_partitions来实现。另外,引用[1]和[2]提到了使用父级聚合进行分割,但那是另一种聚合方式(父子聚合),与分区过滤不同。用户的问题明确是关于分区处理,所以我们主要参考引用[3]。如果用户的数据集非常大,使用分区处理可以有效地分而治之,避免单个聚合操作消耗过多资源。相关问题:1.如何选择合适的分区数量(num_partitions)?2.分区处理对查询性能有什么影响?3.除了分区过滤,Elasticsearch还有哪些处理大数据集聚合的方法?4.在分区聚合中,如何保证排序的正确性?</think>### Elasticsearch 7 Terms聚合分区实现方法 在Elasticsearch 7中,对`terms`聚合进行分区处理需使用**分区过滤(Partition Filter)**功能,通过`include`参数结合`partition`和`num_partitions`实现。这种方法将数据集逻辑分割为多个分区,每次仅处理一个分区的数据,避免内存溢出并提升大数据集处理效率。 #### 核心实现步骤: 1. **分区参数配置** - `num_partitions`: 总分区数(如20) - `partition`: 当前处理的分区编号(从0开始) ```json "terms": { "field": "your_field", "include": { "partition": 0, // 当前分区编号 "num_partitions": 20 // 总分区数 } } ``` 2. **完整DSL示例** 以下查询将`account_id`字段分为20个分区,处理第0个分区的数据,并按`access_date`排序: ```json GET /_search { "size": 0, "aggs": { "partition_results": { "terms": { "field": "account_id", "include": { "partition": 0, // @1 当前分区 "num_partitions": 20 // @2 总分区数 }, "size": 10000, // 分区内最大桶数 "order": { "last_access": "asc" } }, "aggs": { "last_access": { "max": { "field": "access_date" } } } } } } ``` [^3] #### 关键注意事项: 1. **分区均匀性** Elasticsearch使用**哈希算法**分配数据到分区,相同字段值始终分配到同一分区,但分区大小可能不均(取决于数据分布)。 2. **并行处理** 通过多次查询(修改`partition`值)并行处理不同分区: ```python for partition_id in range(20): execute_query(partition_id) # 依次处理0-19分区 ``` 3. **性能优化** - 调整`num_partitions`控制分区粒度(建议值:节点数×2) - 结合`size`限制每个分区的桶数量 - 使用`execution_hint: map`提升速度(适用于高基数字段) #### 应用场景: - 海量数据聚合(如日志分析) - 避免`circuit_breaking_exception`内存溢出错误 - 分布式并行处理加速聚合计算 > **替代方案**:若需跨多字段分区,可结合`composite`聚合Elasticsearch 6.5+),但需注意其分页机制差异[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值