「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」
前言
这是秃头系列的第二个系列,也是关于Elasticsearch的第二篇文章,也是我参加更文挑战的第八天,坚持不易,希望对大家有一定的帮助。
正文
Elasticsearch在数据量很大的情况下如何提高查询性能
要想回答这个问题,就必须先了解一个概念——filesystem cache
filesystem cache
- 往 es 里写的数据,实际上都写到磁盘文件里去了,查询的时候,操作系统会将磁盘文件里的数据自动缓存到 filesystem cache 里面去。
- es 的搜索引擎严重依赖于底层的 filesystem cache,你如果给 filesystem cache 更多的内存,尽量让内存可以容纳所有的 idx segment file 索引数据文件,那么你搜索的时候就基本都是走内存的,性能会非常高。
因此,要让 es 性能要好,最佳的情况下,就是机器的内存,至少可以容纳总数据量的一半。
实战经验
下面我说说我其中的一个做法
- 可以结合使用Es + Hbase
- Es 存储常用的搜索字段, Hbase存储完整的数据
- 主要避免往 es 里写入一行数据所有的字段,但是 90% 的字段是不用来搜索的,结果硬是占据了 es 机器上的 filesystem cache 的空间,单条数据的数据量越大,就会导致 filesystem cahce 能缓存的数据就越少。
- hbase 的特点是适用于海量数据的在线存储,就是对 hbase 可以写入海量数据,但是不要做复杂的搜索,做很简单的一些根据 id 或者范围进行查询的这么一个操作就可以了。例如从 es 中根据 name 和 age 去搜索,拿到的结果可能就 20 个 doc id,然后根据 doc id 到 hbase 里去查询每个 doc id 对应的完整的数据,给查出来,再返回给前端。
- 写入 es 的数据最好小于等于,或者是略微大于 es 的 filesystem cache 的内存容量。
- Es 存储常用的搜索字段, Hbase存储完整的数据
- 做数据预热
- 对于比较热的、经常会有人访问的数据,最好做一个专门的缓存预热子系统,就是对热数据每隔一段时间,就提前访问一下,让数据进入 filesystem cache 里面去。这样下次别人访问的时候,性能一定会好很多。
- 冷热分离
- es可以做类似于 mysql 的水平拆分,就是说将大量的访问很少、频率很低的数据,单独写一个索引,然后将访问很频繁的热数据单独写一个索引。
- 例如可以把当前n天以内的数据写到高配置的机器(最好使用的是固态硬盘)中,作为热数据,剩下的作为历史数据,这样可以分成为实时查询和历史查询,实时查询走热数据索引,历史数据走冷数据索引,保证实时查询的性能,当然这个也要结合具体的业务场景具体分析选择
- document模型设计
- 在es 里面的复杂的关联查询尽量别用,一旦用了性能一般都不太好。
- 最好是先在 Java 系统里就完成关联,将关联好的数据直接写入 es 中。搜索的时候,就不需要利用 es 的搜索语法来完成 join 之类的关联搜索了。
- 分页性能
- es的分页是有一点坑的,例如每页是 10 条数据,你现在要查询第 100 页,实际上是会把每个 shard 上存储的前 1000 条数据都查到一个协调节点上,如果你有个 5 个 shard,那么就有 5000 条数据,接着协调节点对这 5000 条数据进行一些合并、处理,再获取到最终第 100 页的 10 条数据。翻页的时候,翻的越深,每个 shard 返回的数据就越多,而且协调节点处理的时间越长。所以用 es 做分页的时候,你会发现越翻到后面,就越是慢。
- 解决方案:
- 不允许深度分页
- 推荐类似微博这样不断下拉刷出一页页的
- 游标分类 —— scroll api
- 在业务上,根据排序规则对ID进行排序,返回给前端,翻页时前端携带ID过来查找
- 查询优化
- 善用filtered query (bitsets 缓存 复用性强 )
- 使用ngram分词代替模糊查询
- 尽量避免短语查询(Match Phrase Query ES90%的慢查询来自短语查询)
- 善用filtered query (bitsets 缓存 复用性强 )
- 其他
- 在确保业务时效性的基础上尽可能延长refresh时间间隔 (每次refresh都会生成一个新的segment segment太多会影响查询性能)
- 避免删除大量数据 (创建一个新的索引- reindex – 删除旧的索引)
- Reindex数据的时候关闭refresh功能,带数据同步完之后再开启
以上就是我对于一些es的使用心得,希望对大家有一定的帮助
后记
秃头系列-Elasticsearch目前就两篇文章了,关于Elasticsearch的Java Api的使用,后面有时间可能也会写写,其实主要是布尔查询不要太多条件了,不然也是有可能导致OOM的,其他常见api的使用也比较容易上手,好了,我是新生代农民工L_Denny,我们下一个系列再见。