转自微信公众号:Java思维导图

一、前题:

如果面试的时候碰到这样一个面试题:ES 在数据量很大的情况下(数十亿级别)如何提高查询效率?

这个问题说白了,就是看你有没有实际用过ES,因为啥?其实 ES 性能并没有你想象中的那么好。

很多时候数据量大了,特别是有几亿条数据的时候,可能你会懵逼的发现,跑个搜索怎么一下子 5~10s,坑爹了。第一次搜索的时候,是 5~10s,后面反而就快了,可能就几百毫秒。你就可能很懵,用户第一次访问都会比较慢,比较卡吗?所以你要是没玩过ES,或者就是自己玩玩Demo,被问到这个问题很容易懵逼,显示出你对ES确实玩的不怎么样。

说实话,ES 性能优化是没有银弹的。啥意思呢?就是不要期待着随手调一个参数,就可以万能的应对所有的性能慢的场景。也许有的场景是你换个参数,或者调整一下语法,就可以搞定,但是绝对不是所有的场景都可以这样。

二、性能优化杀手锏:Filesystem Cache

你往ES 里写的数据,实际上都写到磁盘文件里去了,查询的时候,操作系统会将磁盘文件里的数据自动缓存到 Filesystem Cache 里面去。

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

性能差距究竟可以有多大?我们之前的很多的测试和压测,如果走磁盘一般肯定是上秒,搜索性能绝对是秒级别的,1秒、5秒、10秒。但如果是走 Filesystem Cache ,是走纯内存的,那么一般来说性能比走磁盘要高一个数量级,基本上就是毫秒级别的,从几毫秒到几百毫秒不等。

这里有个真实的案例:某个公司 ES 节点有 3 台机器,每台机器看起来内存很多 64G,总内存就是 64 * 3 = 192G。每台机器给 ES JVM Heap 是 32G,总共集群里给 Filesystem Cache 的就是 32 * 3 = 96G 内存。而此时,整个磁盘上索引数据文件,在 3 台机器上一共占用了 1T,那么每台机器的数据量是 300G。这样性能好吗?Filesystem Cache 的内存才 100G,十分之一的数据可以放内存,其他的都在磁盘,然后你执行搜索操作,大部分操作都是走磁盘,性能肯定差。

归根结底,你要让 ES 性能好,最佳的情况下,就是你的机器的内存,至少可以容纳你的数据总量的一半。根据我们自己的生产环境实践经验,最佳的情况下,是仅仅在 ES 中就存少量的数据,就是你要用来搜索的那些索引,如果内存留给 Filesystem Cache 的是 100G,那么你就将索引数据控制在 100G 以内。这样的话,你的数据几乎全部走内存来搜索,性能非常之高,一般可以在 1 秒以内。

比如说你现在有一行数据:id,name,age ... 30 个字段,但是你现在搜索,只需要根据 id,name,age 三个字段来搜索。如果你傻乎乎的往 ES 里面写入一行数据所有的字段,就会导致说 90% 的数据不是用来搜索的。结果硬是占据了 ES 机器上的 Filesystem Cache 的空间,单条数据的数据量越大,就会导致 Filesystem Cache 能缓存的数据就越少。其实仅仅写入 ES 中要用来检索的少数几个字段就可以了,比如说写入 ES id,name,age 三个字段。然后你可以把其他的字段数据存在 MySQL/HBase 里,我们一般建议数据用 ES + HBase 这么一个架构。

HBase 的特点是适用于海量数据的在线存储,就是对 HBase 可以写入海量数据,但是不要做复杂的搜索,做很简单的一些根据 id 或者范围进行查询的这么一个操作就可以了。从 ES 中根据 name 和 age 去搜索,拿到的结果可能就 20 个 doc id,然后根据 doc id 到 HBase 里去查询每个 doc id 对应的完整的数据,给查出来,再返回给前端。

写入 ES 的数据最好小于等于,或者是略微大于 ES 的 Filesystem Cache 的内存容量。然后你从 ES 去检索可能就花费 20ms,然后再根据 ES 返回的 id 去 HBase 里查询,查 20 条数据,可能也就耗费个 30ms。可能你原来那么玩儿,1T 数据都放在 ES ,会每次查询都是 5~10s,现在可能性能就会很高,每次查询就是 50ms。

三、数据预热

假如说,哪怕是你就按照上述的方案去做了,ES 集群中每个机器写入的数据量还是超过了 Filesystem Cache 一倍。比如说你写入一台机器 60G 数据,结果 Filesystem Cache 就 30G,还是有 30G 数据留在了磁盘上。

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

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

四、冷热分离

ES 可以做类似 MySQL 的水平拆分,就是说将大量的访问很少、频率很低的数据,单独写一个索引,然后将访问很频繁的热数据单独写一个索引。最好是将冷数据写入一个索引中,然后热数据写入另一个索引中,这样可以确保热数据在被预热之后,尽量都让他们留在 Filesystem Cache 里,别让冷数据给冲刷掉。

你看,假设你有 6 台机器,2个索引,一个放冷数据,一个放热数据,每个索引 3 个 shard。3 台机器放热数据 index,另外 3 台放冷数据 index。这样的话,你大量的时间是在访问热数据 index,热数据可能就占总数据的 10%,此时数据量很少,几乎全部保留在 Filesystem Cache 里面了,就可以确保热数据的访问性能是很高的。但是对于冷数据而言,是在别的 index 里的,跟热数据 index 不在相同的机器上,大家相互之间都没什么联系了。如果有人访问冷数据,可能大量数据是在磁盘上的,此时性能差点,就 10% 的人去访问冷数据,90% 的人在访问热数据,也无所谓了。

五、Document 模型设计

对于MySQL,我们经常有一些复杂的关联查询。在 ES 里面该怎么玩?ES 里面的复杂的关联查询尽量别用,一旦用了性能一般都不大好。最好是现在 Java 系统里就完成关联,将关联好的数据直接写入 ES 中。搜索的时候,就不需要利用 ES 的搜索语法来完成 Join 之类的关联搜索了。

Document 模型设计是非常重要的,很多操作,不要在搜索的时候才想去执行各种复杂的乱七八糟的操作。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 页或者几十页的时候,基本上就要 5~10秒才能查出来一页数据了。有什么解决方案?不允许深度分页(默认深度分页性能都很差)。跟产品经理说,你的系统不允许翻那么深的页,默认翻的越深,性能就越差。

类似于 App 里面的推荐商品不断下拉出来一页一页的;类似微博中,下拉刷微博,刷出来一页一页的,你可以用 Scroll API,关于如何使用,请自行网上搜索。Scroll 会一次性给你生成所有数据的一个快照,然后每次滑动向后翻页就是通过游标 scroll_id 移动,获取下一页,性能很高,都是毫秒级的,缺点是没有随意跳到任意一页的场景,只能一页一页翻。初始化的时候必须指定 Scroll 参数,告诉 ES 要保存此次搜索的上下文多长时间。你需要确保用户不会持续不断翻页几个小时,否则可能因为超时而失败。

除了用 Scroll API ,你也可以用 search_after 来做。search_after 的思想是使用前一页的结果来帮助检索下一页的数据。这种方式也不允许翻页。初始化的时候,需要使用一个唯一值的字段作为 Sort 字段。

出处:https://zhuanlan.zhihu.com/p/60458049

说明:本文来源于网络,版权归原创者所有,如果侵权,烦请告知,谢谢。

本文仅供相互学习交流使用。

[转载] Elasticsearch如何做到亿级数据查询毫秒级返回相关推荐

  1. Elasticsearch如何做到亿级数据查询毫秒级返回?

    https://zhuanlan.zhihu.com/p/60458049 如果面试的时候碰到这样一个面试题:ES 在数据量很大的情况下(数十亿级别)如何提高查询效率? 这个问题说白了,就是看你有没有 ...

  2. JAVA 经典面试题:ES如何做到亿级数据查询毫秒级返回?

    面试题 #elasticsearch#lasticsearch在数十亿级别以上的大量数据下如何提高查询效率,做到毫秒级数据查询呢? 面试官心理分析 在 JAVA 高级面试中这个问题肯定是要被问及的,为 ...

  3. currenttimemillis 毫秒还是秒_Elasticsearch(ES)如何做到亿级数据查询毫秒级返回

    前言: 这个问题其实是更面向原理及实操方面的内容.换个问法,可以是这样来问:ES 在数据量很大的情况下(数十亿级别)如何提高查询效率? 为了精简,如下内容将Elasticsearch简称为ES 如果你 ...

  4. 经典面试题:ES如何做到亿级数据查询毫秒级返回?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:8rr.co/5Csc 面试题 es 在数据量很大的情况下( ...

  5. ES如何做到亿级数据查询毫秒级返回

    一.面试题 ES在数据量很大的情况下(数十亿级别)如何提高查询效率? 二.面试官心理分析 这个问题是肯定要问的,说白了,就是看你有没有实际干过ES,因为啥?其实ES性能并没有你想象中那么好的.很多时候 ...

  6. 知乎1.3万亿条数据查询毫秒级响应,如何做到的?

    点击"开发者技术前线",选择"星标????" 在看|星标|留言,  真爱 来自:孙晓光 | 责编:乐乐 链接:dzone.com/articles/lesson ...

  7. 查询亿级数据毫秒级返回!牛逼哄哄的ElasticSearch是如何做到的?

    一道面试题的引入: 如果面试的时候碰到这样一个面试题:ElasticSearch(以下简称ES) 在数据量很大的情况下(数十亿级别)如何提高查询效率? 这个问题说白了,就是看你有没有实际用过 ES,因 ...

  8. pymongo 亿级数据查询技术总结之一

    文章目录 序言 亿级数据下find的性能 count 的测试结果 数据库优化首要策略: 加索引就好? 序言 这么多年来做过好几个使用mongodb的项目, 这里主要记录下大数据使用上的一些技巧和要点. ...

  9. Elasticsearch如何做到数十亿数据查询毫秒级响应?

    如果面试的时候碰到这样一个面试题:ES 在数据量很大的情况下(数十亿级别)如何提高查询效率? 这个问题说白了,就是看你有没有实际用过 ES,因为啥?其实 ES 性能并没有你想象中那么好的. 很多时候数 ...

最新文章

  1. sklearn 套件的主要内容_sklearn-roc_curve
  2. Paxos算法之旅(四)zookeeper代码解析--转载
  3. 【Django】安装及配置
  4. ADS错误(Fatal)L6002U解决方法
  5. IBM MQ 使用指南
  6. UBUNTU修改控制台语言
  7. 腾讯为60亿美元债券定价 为1年来亚洲最大美元债发行交易
  8. hbase scala 实例_scala操作HBase2.0
  9. 三大统计相关系数:Pearson、Spearman秩相关系数、kendall等级相关系数
  10. 网站性能优化——雅虎14条
  11. 免费文章原创度检测工具
  12. 报价单常见问题及高效拯救你的报价实用手册
  13. 263企业邮箱服务器是什么,千万别用263企业邮箱 - 外贸邮箱邮件群发 - 电脑网络 - 福步外贸论坛(FOB Business Forum) |中国第一外贸论坛...
  14. 看了本文让你laravel安装laravel-queue-rabbitmq一路顺风
  15. Adobe或QQ的oxc000007b错误解决方案.
  16. PNAS:大脑是如何计算主观价值的?
  17. 双通道(双CPU)服务器主板上内存条的安装方式
  18. 手指和手势识别算法原理和解析
  19. Python 网络编程(6)总结【转】
  20. 118、验证有效期JWT实施方案

热门文章

  1. 饺子(节操)播放器集成问题
  2. 箱线图怎么看_股票000882:怎么看月k线图「歙县股票网」
  3. FOSS社区可以拯救197种濒临灭绝的印度语言吗?
  4. java流水线工程设计_进阶项目(7)流水线设计讲解
  5. 等候·《致我们终将逝去的青春》
  6. ImportError: cannot import name ‘SummaryWriter‘ from partially initialized module ‘torch.utils.tenso
  7. [HNOI2004] 敲砖块(dp + 前缀和)
  8. 使用pandas的drop函数删除数据
  9. 苹果手表与服务器连接中断,Apple Watch与iPhone连接不上怎么办【解决方案】
  10. 2020年十大黑科技:新冠疫苗当仁不让,脑机接口引领风潮