Elasticsearch是基于 Lucene 架构实现的分布式、海量数据的存储分析引擎,其中 Lucene 最主要的倒排索引结构,赋予了ES全文检索、模糊匹配、联合索引查询等等快速检索文档数据的能力,使得ES在这些查询的应用场景下优于数据库。
倒排索引:被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。
基本概念:
- Cluster,集群。一个集群包含多个节点,对外提供服务。
- Node,节点。一个节点运行在一个独立的环境或虚拟机上,一个节点可以包含多个分片,一个索引由多个分片组成
- Shard,分片。(Primary Shard 和 Replica Shard)
- Index,索引,相当于mysql中的库。
- Type,类型,一个索引可以对应一个或者多个类型。(ES6.0后被废弃,ES7完全删除)
- Mapping,映射,相当于表结构。
- Document,文档,相当于行。
- Field,字段,相当于列。
分片与副本的区别在于:
- 当分片设置为5,数据量为30G时,ES会将数据平均分配到5个分片上,每个分片6G数据。进行数据查询时,ES会把查询发送给每个分片,最后将结果组合在一起。目的是保障查询的高效性。
- 副本是对分片的数据进行复制,目的是保障数据的高可靠性,防止丢失。
Filter VS Query
尽可能使用过滤器上下文(Filter)替代查询上下文(Query)
- Query:此文档与此查询子句的匹配程度如何?
- Filter:此文档和查询子句匹配吗?
Elasticsearch 针对 Filter 查询只需要回答「是」或者「否」,不需要像 Query 查询一样计算相关性分数,同时Filter结果可以缓存。
Reindex 重建索引的原理:
Scroll Query + Bulk
Ingest pipeline 可以在数据存入ES之前对数据进行转换,例如转小写,增加字段等。
数据写入原理
大概分为三个步骤:write -> refresh -> flush
1、write:文档数据到内存缓存,并存到 translog
2、refresh:内存缓存中的文档数据,到文件缓存中的 segment 。此时可以被搜到。
3、flush: 缓存中的 segment 文档数据写入到磁盘
当数据添加到索引后并不能马上被查询到,等到索引刷新后才会被查询到。refresh_interval 参数设置为正数之后,需要等相应时间后才可以在es索引中搜索到,因为已经从内存缓存刷新到文件缓存中了。详见数据写入与查询存在时间差问题
性能优化:
背景:每五分钟就有6.5M条数据,直接reindex需要1000s(15分钟)
- 创建索引前设置主分片数量为二,副本比例为一,700s
- batch size = 2000(原来为默认值1000), 副本比例为零,480s
- slice = 2(其实是三个并行任务,一个父任务二个子任务),420s(甚至有一次350s)
text 和 keyword 的区别
text类型: text类型是指可分词的文本,适用于长文本或短语查询。当文本被索引时,会被分成一些个别单词或词组,并且会去除停用词(如“a”、“the”、“and”等)和标点符号。这些单词或词组将被标准化并存储在倒排索引中,使得搜索时可以更快地匹配文档。适合全文搜索。
keyword类型: keyword类型是指未经过分词处理的文本,适用于精确匹配和排序。当文本被索引时,会被作为一个整体进行索引。它们通常用于搜索和排序非文本字段,例如数字或日期。适合过滤、排序、聚合。
ElasticSearch 默认为text类型,但是text类型总会有keyword的类型的字段,等价于 .keyword
ES 调优
硬件配置优化
- CPU 配置
- 内存配置
- 禁止 swap
- 配置 GC
- 磁盘
索引优化
- 批量提交(Bulk),但不能一次性提交过多内容。
- 增加 refresh 时间间隔
- 减少副本数量
查询优化
- 尽可能使用过滤器上下文(Filter)替代查询上下文(Query)
- 拆分索引
- 减少模糊匹配
数据结构优化
- 减少不需要的字段
- text 和 keyword 类型字段的设置
集群架构设计
- 设置分片数量,但不宜过大。