何为索引设计?
数据写入之前,提前创建索引设置和数据结构,已达到性能,稳定性和资源利用最大化,通常包括以下方面:
- 索引存储量评估
- 索引读写情况
- 分片设置
- 副本设置
- 索引字段类型与扩展
- 性能参数调优
下面结合Setting和Mapping设计
Setting设计
业务类型
- 写多读少:压力主要在写入端,
- 读多写少:对于查询量大的索引,要保证查询性能优先,可以设置更多的分片数以分摊性能
分片设置
分片(shard)是es存储数据的文件块,主要有两种作用:
- 水平扩展
- 提高读写性能和吞吐量
数据写入时,每个 doc 会根据routing进行路由:shard = hash(routing)%number_of_primary_shards
所以可以指定路由键保证同类型数据落到同一分片,查询时省去分片协调的时间,但需考虑数据倾斜
一旦创建了分片数,无法更改。
Elastic 官方推荐的单分片大小存储控制在 20GB~40GB 之间,不要超过 50GB,如果单分片存储量超出范围过大,会出现如下问题:
- 超出单分片文档数限制:es限制doc数为Integer.MAX_VALUE : 2,147,483,519
- 恢复速度慢: 节点重启、分片恢复的时候时间就会越长,IO 压力也会越大。同时会影响查询性能
- 迁移成本高: 增加迁移索引数据迁移时间成本
副本设置
副本( replicas )主要用来提供集群的高可用。
副本的缺点:影响集群写入性能(写入的时候会主副分片都写入数据)与提升一倍的存储成本
副本的优点:提升查询性能(查询的时候可以主、副分片并行执行)
但是如果要保证高可用,一定要保证最少为 1
Mapping设计
es分为动态映射和静态映射。其中动态映射指数据写入 ES 索引时进行动态映射匹配,静态映射则需要手动指定,业务模型已知的情况下,尽可能使用静态设计。对于不确定的字段,可以结合动态 mapping 进行控制
设计流程
- 评估业务数据字段个数(常态化的)
- 根据不同的字段评估类型,并判断是否需要检索
- 评估字段是否需要排序、聚合分析。如果是text类型字段,需要聚合分析的,需要开启 fielddata
完整参考:www.elastic.co/guide/en/el…
注意事项
- ES不支持删除已有字段
- ES不支持修改字段类型
实战建议
硬件层面
- 内存到位:严重依赖文件系统缓存来加快搜索速度。通常,你应该确保至少有一半的可用内存进入文件系统缓存,以便 Elasticsearch 可以将索引的热点区域保留在物理内存中。
- 磁盘到位:对写入速度有超高要求的,必要时换SSD
- CPU核数和线程数:基于CPU 核数合理调节线程池和队列的大小
Settings层面
- 分片大小:单分片控制在 20~40G 内。单分片支持的 doc 数量在2,147,483,519。
- 分片数量:建议趋近于节点数,提升并发性能
- 副本数量:reindex 数据建议为 0 个;生产使用建议至少 1 个
- total_shards_per_node:如果分片数小于等于节点数,建议1个。否则按比例增加即可。
- refresh_interval: 时效性要求高建议用默认 1s ,否则建议设置在 30~60s 左右。
Mappings层面
- templates 使用:对于同一类型索引进行提炼,提前做 templates ,方便后期灵活调整。
- keyword、text:精准查询与聚合计算使用 keyword 、分词检索使用text;
- 动态templates:对于不确定的字段需要设置类型映射,可以考虑使用。
- 字段数量:单索引推荐字段数 1000 以内
- 对象嵌套:默认限制嵌套 20 层,建议不要超过 3 层
- 属性设置:根据业务情况,针对不同字段类型进行属性设置。比如对于不查询检索的字段,设置 index:false,字段类型能用keyword就不要用其他
Search层面
-
尽可能减少检索字段数量
-
控制返回字段和结果
-
合理设置size大小,深度分页建议scroll
-
规避使用脚本
-
有效利用filter:可以用到缓存,和query 相比,不需要计算评分,所以更快。