面试题答案
一键面试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
参数开启查询缓存,例如:
- 利用Elasticsearch的查询缓存机制,对于频繁查询的聚合结果进行缓存。可以通过设置
{
"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
}
}
}
}
}
}