ElasticSearch query performance optimization

📌Elasticsearch使原生的Lucene查询更加简单,同时提供了更多的功能,且可以通过RESTful API访问。Elasticsearch是一个分布式的搜索引擎,提供了一个分布式多用户能力的全文搜索引擎,基于RESTfulweb接口。此外也可以扩展到几乎无限数量的服务器,以及能力去处理PB级别的数据。

📚 核心概念

🔒 基本概念

为了方便理解Elasticsearch的一些基本概念,将其中的一些概念和关系型数据库做类比。但是请注意,这样类比并不是非常合适,甚至可能存在一些偏差,仅适用为初期提供更好的理解。

Elasticsearch Mysql
索引库Index 数据库Database
文档类型Type(ES6.0开始逐渐弃用) 数据表Table
文档Document 行数据Row
字段Field 具体到某一列Column
文档ID 主键ID
查询Query DSL 查询SQL
Get http://... SELECT * FROM...
PUT http://... UPDATE TABLE SET...
  • Index是文档的集合,相当于关系型数据库中的数据库,一个Index可以包含多个Type,但是在ES6.0版本中逐渐弃用Type,一个Index只能包含一个Type
    • 索引名称必须是小写的,不能包含逗号、空格等特殊字符
    • 索引有mappingsetting两个配置,mapping定义了文档的字段类型,setting定义了索引的配置例如分片、副本和自定义的analyzer
  • Document是可搜索数据的最小单元,相当于关系型数据库中的一条记录,在ES中会被序列化成Json格式存储
  • 存储的Json对象由各个字段组成,相当于关系型数据库中的列,同时每个字段也有其自己的类型(字符串、布尔、时间范围等)
  • 创建文档时若不指定字段的类型,ES将自动匹配映射,但是在生产环境中最好自定义映射
  • 每个文档都有一个ID相当于Mysql的主键,可以自定也可以自动生成
  • 节点Node是一个单独的Elasticsearch实例,它属于一个集群Cluster,集群是由一个或多个节点组成的,本质上一个节点可简单看作是一个进程,在集群中建议在单机只部署一个高性能节点,单机多节点反而导致性能下降;同样也具有一般分布式架构的选举、coor
  • 分片Shard是ES中最小的工作单元,每个分片都是一个Lucene实例,分片是ES实现分布式和水平扩展的基础,分片的数量在索引创建时就已经确定,分片的数量只能增加不能减少,一般不建议后期再次修改
  • 副本Replica是分片的副本,副本的作用是提高数据的可用性,副本的数量可以动态调整,副本的数量越多,读性能越好,但是写性能会下降,副本的数量不能超过节点的数量,默认副本系数为1,也就是给每个主分片创建一个copy
  • 关于Type,多Type里的字段需要保持一致,也就是不同实体之间出现了很多冗余,导致分布稀疏,干扰了Lucene压缩文档的能力,影响存储性能;相对于Mysql中每个Table下的Scheme是没有限制要保持一致的,这也是区别之一
    • 6.x之前可以有多个Type
    • 6.x之后只能有一个自定义名字的文档类型
    • 7.x之后只能有一个且名字是_doc
    • 未来可能取消文档类型的概念,部分API将改动

查询性能优化

Filesystem Cache 文件系统缓存

数据写入流程:客户端选择一个Node发送请求,路由到主分片,主分片将数据先写入到buffer里,同时将数据写到translog日志(同步写入到副本分片),可选写到translog的同时同步写入磁盘或者等待后异步刷到磁盘;若buffer满了或是手动触发刷新refresh,就会刷新到Filesystem Cache,此时生成一个新的segment就可以被搜索到,一定时间或translog超出大小后触发flushFilesystem Cache数据同步到磁盘然后清空translog简而言之,写数据都写到磁盘里了,搜索从磁盘里搜索才是查询性能的瓶颈所在

  • 尽可能给filesystem cache分配更多内存,最佳情况是大于ES所需要搜索的数据大小,可以保证容纳所有索引数据,搜索全部走内存的话性能非常高
  • 硬件配置的提升的有限度的,可以考虑减少存储的索引规模,只存储需要搜索的索引,将idnameage等字段存入ES,将其他数据存在HBase等适合存放大规模在线数据的数据库,从ES中查询到关键字段再去Hbase中查完整的数据

数据冷热分离

无法完全保证Filesystem Cache大于数据量时,考虑分离热点数据和冷数据

  • 间隔一段时间自动搜索热点数据,保证热点数据始终在Filesystem Cache里,其实就是做一个预热的子系统
  • 拆分冷热数据构建不同的索引,防止热数据被冷数据冲刷掉,其实就是做类似于Mysql的分库,以牺牲冷数据的查询性能来提升热数据的查询性能

分页查询优化

  • 尽量避免复杂的操作,例如join查询
  • 和Mysql类似,分页查询越后面越慢,深度分页性能很差,也就是需要先做一个过滤,那么过滤用什么方式?
    • 使用scroll api进行深度分页,但是作者不再推荐使用这个,scroll将一次性给出所有数据的快照谢谢,然后通过scroll_id移动查询,后续的查询基本都将是毫秒级,但不能实现跳转,同时数据实时性存在缺陷
    • 使用search_after利用前一页的检索结果来帮助检索下一页,同样这也无法实现随意跳转,官方推荐使用 _uid作为全局唯一值,其实使用业务层的id也可以,在模型设计时需要考虑预留一个用于sort的字段
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

请我喝杯咖啡吧~