MST

星途 面试题库

面试题:ElasticSearch复杂聚合查询在金融交易数据分析中的优化

在金融交易数据场景下,数据量庞大,包含交易时间、交易金额、交易类型、交易地区等多维度信息。需求是进行复杂聚合查询,比如按交易地区和交易类型统计交易金额总和,并且要在聚合结果上进行二次聚合,找出交易金额总和排名前5的地区 - 交易类型组合,同时要优化查询性能以应对大数据量。请阐述完整的实现方案,包括索引设计、聚合策略、性能优化措施以及对应的ElasticSearch DSL代码。
15.2万 热度难度
数据库ElasticSearch

知识考点

AI 面试

面试题答案

一键面试

1. 索引设计

  • 字段类型
    • 交易时间:使用date类型,确保日期格式正确,以便按时间范围查询。
    • 交易金额:使用double类型,以存储精确的金额数值。
    • 交易类型交易地区:使用keyword类型,因为它们是离散的分类数据,适合用于聚合操作。
  • 索引结构
    • 为了加快按交易地区和交易类型的聚合查询,可以在这两个字段上建立复合索引。在Elasticsearch中,虽然没有传统数据库那样显式的复合索引创建语法,但合理的映射定义和查询结构可以达到类似效果。例如,定义映射如下:
{
  "mappings": {
    "properties": {
      "交易时间": {
        "type": "date"
      },
      "交易金额": {
        "type": "double"
      },
      "交易类型": {
        "type": "keyword"
      },
      "交易地区": {
        "type": "keyword"
      }
    }
  }
}

2. 聚合策略

  • 一级聚合
    • 使用terms聚合按交易地区交易类型分组,再使用sum聚合计算每个分组的交易金额总和。例如:
{
  "aggs": {
    "地区 - 交易类型分组": {
      "composite": {
        "size": 10000,
        "sources": [
          {
            "交易地区": {
              "terms": {
                "field": "交易地区"
              }
            }
          },
          {
            "交易类型": {
              "terms": {
                "field": "交易类型"
              }
            }
          }
        ]
      },
      "aggs": {
        "交易金额总和": {
          "sum": {
            "field": "交易金额"
          }
        }
      }
    }
  }
}

这里使用composite聚合而不是简单的terms聚合,因为composite聚合在大数据量下性能更好,并且可以处理超过10000条的聚合结果(默认terms聚合最多返回10000条结果)。

  • 二级聚合
    • 在一级聚合的结果上,使用top_hits聚合找出交易金额总和排名前5的地区 - 交易类型组合。在一级聚合的aggs下添加如下内容:
{
  "前5名地区 - 交易类型组合": {
    "top_hits": {
      "sort": [
        {
          "交易金额总和.value": {
            "order": "desc"
          }
        }
      ],
      "size": 5
    }
  }
}

3. 性能优化措施

  • 数据分片与副本
    • 根据数据量和集群规模合理设置分片数和副本数。如果数据量非常大,可以适当增加分片数,但要注意过多分片会增加集群管理开销。例如,对于上亿条数据,可以设置10 - 20个分片,副本数可以设置为1 - 2个,以提高数据的可用性和读取性能。
  • 缓存
    • 利用Elasticsearch的查询缓存机制,对于频繁查询的聚合结果进行缓存。可以通过设置request_cache参数开启查询缓存,例如:
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    // 聚合内容
  },
  "request_cache": true
}
  • 批量操作
    • 在数据写入时,尽量使用批量操作(bulk API),减少I/O开销和网络请求次数。

4. ElasticSearch DSL代码

完整的ElasticSearch DSL代码如下:

{
  "aggs": {
    "地区 - 交易类型分组": {
      "composite": {
        "size": 10000,
        "sources": [
          {
            "交易地区": {
              "terms": {
                "field": "交易地区"
              }
            }
          },
          {
            "交易类型": {
              "terms": {
                "field": "交易类型"
              }
            }
          }
        ]
      },
      "aggs": {
        "交易金额总和": {
          "sum": {
            "field": "交易金额"
          }
        },
        "前5名地区 - 交易类型组合": {
          "top_hits": {
            "sort": [
              {
                "交易金额总和.value": {
                  "order": "desc"
                }
              }
            ],
            "size": 5
          }
        }
      }
    }
  }
}