本文章来源于:https://github.com/Zeb-D/my-review ,请star 强力支持,你的支持,就是我的动力。

[TOC]


提问

面对着这么一个庞然大物,我们除了代码API写的六、知道一些ElasticSearch入门介绍外,有时候我这个人挺会怀疑我自己用到别人的代码或者框架,但是自己又写不出来,没办法只好啃源码。

说白了,任何程序运行要如何达到你期待的效果,这是一个漫长的路;

  • ES的查询原理是怎么流转的

  • ES 为什么会在线上变慢

  • ES 到底要放些什么数据或者字段

  • ES到底需要配置多少内存

  • ES为什么分页越深越慢

  • ES什么时候需要单独建索引

ES查询原理

你在调用es写数据的api的时候,这里到底是写道缓存中,还是磁盘文件中?

是否曾知道,ElasticSearch 的缓存长的什么样?

[这里是图片001]

在客户端进程与es机器进程交互主要是api通信,但es进程内部又做了些什么?

es会走具体的分片,再走内存中的文件系统缓存(filesystem cache),·filesystem cache·这是es 搜索引擎的核心,最底层的;

缓存没面中后,才会去读取磁盘文件,最终才决定是返回什么数据。

所以

es 的搜索引擎严重依赖于底层的 filesystem cache,你如果给 filesystem cache 更多的内存,尽量让内存可以容纳所有的 idx segment file 索引数据文件,那么你搜索的时候就基本都是走内存的,性能会非常高。

ElasticSearch 会变慢

有时候,测试环境、线上环境的性能差是不一样的,随着时间的变化,性能差也变明显了,这究竟是什么导致的?

比如:我们之前很多的测试和压测,如果走磁盘一般肯定上秒,搜索性能绝对是秒级别的,1秒、5秒、10秒。

但如果是走 filesystem cache,是走纯内存的,那么一般来说性能比走磁盘要高一个数量级,基本上就是毫秒级的,从几毫秒到几百毫秒不等。

身边有个真实的案例

某个公司 es 节点有 3 台机器,每台机器看起来内存很多,64G,总内存就是 64 * 3 = 192G。每台机器给 es jvm heap 是 32G,那么剩下来留给 filesystem cache 的就是每台机器才 32G,总共集群里给 filesystem cache 的就是 32 * 3 = 96G 内存。

而此时,整个磁盘上索引数据文件,在 3 台机器上一共占用了 1T 的磁盘容量,es 数据量是 1T,那么每台机器的数据量是 300G。这样性能好吗?

filesystem cache 的内存才 100G,十分之一的数据可以放内存,其他的都在磁盘,然后你执行搜索操作,大部分操作都是走磁盘,性能肯定差。

归根结底,你要让 es 性能要好,最佳的情况下,就是你的机器的内存,至少可以容纳你的总数据量的一半。

我身边也有一个非常成功的生产环境实践经验:

最佳的情况下,是仅仅在 es 中就存少量的数据,就是你要用来搜索的那些索引,如果内存留给 filesystem cache 的是 100G,那么你就将索引数据控制在 100G 以内,这样的话,你的数据几乎全部走内存来搜索,性能非常之高,一般可以在 1 秒以内。

ElasticSearch 合理塞字段

但是,内存这种资源,要合理的放数据,放的多了,索引文件就变多了,内存就这么耗去了。

可能在开发的时候,估计把整个数据硬塞到ElasticSearch ,但是真正的使用查询了用了几个字段;

id,name,age .... 30 个字段。但是你现在搜索,只需要根据 id,name,age 三个字段来搜索。

如果你傻乎乎往 es 里写入一行数据所有的字段,就会导致说 90% 的数据是不用来搜索的,结果硬是占据了 es 机器上的 filesystem cache 的空间,单条数据的数据量越大,就会导致 filesystem cahce 能缓存的数据就越少。

其实,仅仅写入 es 中要用来检索的少数几个字段就可以了

这时候你可能会想,剩下的数据字段要查询怎么办?

我们可以这么进行操作,先查询ElasticSearch,得到一个Id,再在传到其他DB(如mysql/hbase)进行查询,

比如我曾经的公司就用es + hbase 这么一个架构,主要用于保存日志,这个日志一般通过kafka进行收集,但落地是有两个部分的,关键数据会过一下es,再统一保存到hbase。

hbase 的特点是适用于海量数据的在线存储,就是对 hbase 可以写入海量数据,

但是不要做复杂的搜索,做很简单的一些根据 id 或者范围进行查询的这么一个操作就可以了。

比如:

从 es 中根据 name 和 age 去搜索,拿到的结果可能就 20 个 doc id,然后根据 doc id 到 hbase 里去查询每个 doc id 对应的完整的数据,给查出来,再返回给前端。

总结一下,怎么在有限的es配置的内存塞数据:

写入 es 的数据最好小于等于,或者是略微大于 es 的 filesystem cache 的内存容量。

然后你从 es 检索可能就花费 20ms,

然后再根据 es 返回的 id 去 hbase 里查询,查 20 条数据,可能也就耗费个 30ms,

1T 数据都放es,会每次查询都是 5~10秒,现在可能性能就会很高,每次查询就是 50ms。

所以,塞数据的多少与你配置的内存资源有关,有钱的话,塞什么字段都没关系!!!自嘲下

如何保证es的查询不落到磁盘

数据预热

假如说,es 集群中每个机器写入的数据量还是超过了 filesystem cache 一倍,比如说你写入一台机器 60G 数据,结果 filesystem cache 就 30G,还是有 30G 数据留在了磁盘上。

其实可以做数据预热。专门为那些高访问的数据加热到es中

举个例子,拿微博来说,你可以把一些大V,平时看的人很多的数据,你自己提前后台搞个系统,每隔一会儿,自己的后台系统去搜索一下热数据,刷到 filesystem cache 里去,后面用户实际上来看这个热数据的时候,他们就是直接从内存里搜索了,很快。

或者是电商,你可以将平时查看最多的一些商品,比如说 iphone 8,热数据提前后台搞个程序,每隔 1 分钟自己主动访问一次,刷到 filesystem cache 里去。

对于那些你觉得比较热的,经常会有人访问的数据,最好做一个专门的缓存预热子系统,就是对热数据每隔一段时间,就提前访问一下,让数据进入 filesystem cache 里面去。这样下次别人访问的时候,一定性能会好一些。

冷热分离

我们在进行项目开发,往往不可能想到比较周到,有可能半路的时候加个中间件 来做个各种优化;

我们上面只是说了个大概塞什么数据到ES,然后数据量与ES内存量的比列;我们在上片文章知道查询es其实是通过走索引的;

现在我们将大量访问的数据放到这个中间件(有点像缓存)中,es 可以做类似于 mysql 的水平拆分,就是说将大量的访问很少、频率很低的数据,单独写一个索引,然后将访问很频繁的热数据单独写一个索引。最好是将冷数据写入一个索引中,然后热数据写入另外一个索引中,这样可以确保热数据在被预热之后,尽量都让他们留在 filesystem os cache 里,别让冷数据给冲刷掉

你看,假设你有 6 台机器,2 个索引,一个放冷数据,一个放热数据,每个索引 3 个shard。

3 台机器放热数据 index;另外 3 台机器放冷数据 index。然后这样的话,你大量的时候是在访问热数据 index,热数据可能就占总数据量的 10%,此时数据量很少,几乎全都保留在 filesystem cache 里面了,就可以确保热数据的访问性能是很高的。

但是对于冷数据而言,是在别的 index 里的,跟热数据 index 不在相同的机器上,大家互相之间都没什么联系了。如果有人访问冷数据,可能大量数据是在磁盘上的,此时性能差点,就 10% 的人去访问冷数据,90% 的人在访问热数据,也无所谓了。

减少复杂的关联查询

我们经常使用Mysql,也不可避免看到es有这功能,就经常使用一些复杂的关联查询。

es 能支持的操作就是那么多,不要考虑用 es 做一些它不好操作的事情。如果真的有那种操作,尽量在 document 模型设计的时候,写入的时候就完成。

另外对于一些太复杂的操作,比如 join/nested/parent-child 搜索都要尽量避免,性能都很差的。

分页性能优化

es 的分页是较坑的,为啥呢?假如你每页是 10 条数据,你现在要查询第 100 页,实际上是会把每个 shard 上存储的前 1000 条数据都查到一个协调节点上,如果你有个 5 个shard,那么就有 5000 条数据,接着协调节点对这 5000 条数据进行一些合并、处理,再获取到最终第 100 页的 10 条数据。

分布式的,你要查第100页的10条数据,不可能说从5个 shard,每个 shard 就查 2 条数据?

最后到协调节点合并成 10 条数据?你必须得从每个 shard 都查 1000 条数据过来,然后根据你的需求进行排序、筛选等等操作,最后再次分页,拿到里面第 100 页的数据。你翻页的时候,翻的越深,每个 shard 返回的数据就越多,而且协调节点处理的时间越长。非常坑爹。所以用 es 做分页的时候,你会发现越翻到后面,就越是慢。

我们之前也是遇到过这个问题,用 es 作分页,前几页就几十毫秒,翻到 10 页 or 几十页的时候,基本上就要 5~10秒 才能查出来一页数据了。

有什么解决方案吗?

不允许深度分页/默认深度分页性能很惨

你系统不允许翻那么深的页,跟产品经理说,默认翻的越深,性能就越差。

类似于 app 里的推荐商品不断下拉出来一页一页的

类似于微博中,下拉刷微博,刷出来一页一页的,你可以用 scroll api,关于如何使用,自行上网搜索。

scroll 会一次性给你生成所有数据的一个快照,然后每次翻页就是通过游标移动,获取下一页下一页这样子,性能会比上面说的那种分页性能也高很多很多,基本上都是毫秒级的。

但是 唯一的一点就是,这个适合于那种类似微博下拉翻页的,不能随意跳到任何一页的场景。也就是说,你不能先进入第 10 页,然后去 120 页,然后又回到 58 页,不能随意乱跳页。所以现在很多产品,都是不允许你随意翻页的,app,也有一些网站,做的就是你只能往下拉,一页一页的翻。

另外,这个 scroll 是要保留一段时间内的数据快照的,你需要确保用户不会持续不断翻页翻几个小时。

ElasticSearch之查询性能分析相关推荐

  1. MySQL简单查询性能分析

    MySQL简单查询性能分析  建立如此结构的数据表,并插入110万条随机记录,进行查询性能测试.   插入110万条随机记录后,数据表的大小为102MB. 现在使用phpMyAdmin自带的SQL查询 ...

  2. ElasticSearch 海量数据查询性能优化

    ElasticSearch 海量数据查询性能优化 尽量让查询计算简单 最大化使用操作系统的文件缓存 增加内存 减少 ES 中的数据量 思路扩展 冷热分离 数据预加载 小结 ES 接收到查询请求后,会转 ...

  3. Elasticsearch 分页查询聚合分析

    分页查询 关于 Elasticsearch 分页查询,这几个问题经常被问到 问题1:想请问下,一次性获取索引上的某个字段的所有值(100 万左右),除了把 max_result_window 调大 , ...

  4. MongoDB查询性能分析

    explain()方法能够提供大量与查询相关的信息.对于速度比较慢的查询来说,它是最重要的性能分析工具之一.通过查看一个查询的explain()输出信息,可以知道查询使用了哪个索引,以及是如何使用的. ...

  5. Elasticsearch提高查询性能的方法

    ES性能并没有想象中那么好.很多时候数据量大了,特别是有几亿条数据的时候,可能第一次搜索的时候,是5-10s,后面反而就快了,可能就几百毫秒. 说实话,ES 性能优化不要期待着随手调一个参数,就可以万 ...

  6. MongoDB查询性能分析—— explain 操作返回结果详解

    MongoDB 提供 db.collection.explain(), cursort.explain() 及 explain 命令获取查询计划及查询计划执行统计信息. explain 结果将查询计划 ...

  7. [MySQL]--查询性能分析工具-explain关键字

    explain显示了MySQL如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. explain的使用方法很简单,只需要在select查询语句前面加上expl ...

  8. Es底层查询原理、数据结构、及性能分析

      Elasticsearch是一个很火的分布式搜索系统,提供了非常强大而且易用的查询和分析能力,包括全文索引.模糊查询.多条件组合查询.地理位置查询等等,而且具有一定的分析聚合能力.因为其查询场景非 ...

  9. 数据库与elasticSearch,大数据查询性能PK

    每天早上七点三十,准时推送干货 一.介绍 在这篇文章中 利用springboot+elasticSearch,实现数据高效搜索,实战开发,我们介绍了 SpringBoot 整合 ElasticSear ...

最新文章

  1. oracle 存储过程 状态,查看ORACLE中正在运行的存储过程 | 学步园
  2. 深入理解C++中public、protected及private用法
  3. Flask-Email的相关知识点实现(发送电子邮件)
  4. linux 中文输入法 xshall,Centos6.7下安装ibus中文输入法
  5. Linux学习(CentOS-7)---磁盘分区(概念、分区方法、分区方案)
  6. module ‘imgaug.augmenters‘ has no attribute ‘Resize‘
  7. Programming asp.net笔记--第三章 Controls: Fundamental Concepts
  8. python异步写文件_结合异步http请求将数据写入文件
  9. Nancy简单实战之NancyMusicStore(二):打造首页
  10. BCNF/3NF的判断方法
  11. 我们团队一位自学Android的经验总结
  12. Nero 软件各种组件简单介绍
  13. 计算机搜索不到网络打印机怎么处理,搜索不到网络打印机怎么办 搜索不到网络打印机解决方法...
  14. 根据子节点递归查询所有父节点
  15. 中文文本关键词抽取的三种方法(TF-IDF、TextRank、word2vec)
  16. 全卷积网络FCN与卷积神经网络CNN的区别
  17. Linear Algebra 线性代数
  18. 什么是敏捷开发?敏捷开发流程的8个步骤
  19. 接口练习(台灯案例)
  20. 计算机怎么设置按音乐,Win7笔记本怎么设置开机音乐?电脑开机音乐如何设置?...

热门文章

  1. 前端零基础编译原理科普
  2. python弹球游戏移动球拍_python编写弹球游戏的实现代码
  3. poco 编译mysql_Poco 自动全编译的方法 | 学步园
  4. IDEA方法注释模板
  5. 我的第一台笔记本电脑
  6. Python案例实战:天气数据集爬取 + 多组可视化图表分析
  7. 学习能力与思维模式是一个人的核心竞争力
  8. 简信CRM分享:使用移动CRM工作更简信CRM!
  9. java字符串替换括号(中文和英文括号),通过正则表达式替换,如果直接替换中文可以替换,但是英文替换会报错
  10. 解决chrome被流氓百度的hao123劫持问题