es性能优化没有银弹!
(1)性能优化的杀手锏——filesystem cache (即 os cache,操作系统的缓存)
es的搜索引擎严重依赖于底层的filesystem cache,
你如果给filesystem cache更多的内存,尽量让内存可以容纳所有的indx segment file索引数据文件,那么你搜索的时候就基本都是走内存的,性能会非常高。
比如说,你一共要在es中存储1T的数据,那么你的多台机器留个filesystem cache的内存加起来综合,至少要到512G,
至少半数的情况下,搜索是走内存的,性能一般可以到几秒钟,2秒,3秒,5秒
如果最佳的情况下,filesystem cache 的大小 大于 ES所需要搜索的数据大小。
ES中只写入需要索引的那几个字段,不要把整条记录都写到 ES中。
比如说,ES就写入 id name age三个字段就可以了,然后你可以把其他的字段数据存在hbase或mysql中,建议是HBase。
hbase的特点是适用于海量数据的在线存储,就是对hbase可以写入海量数据,不要做复杂的搜索,就是做很简单的一些根据id或者范围进行查询的这么一个操作就可以了
从es中根据name和age去搜索,拿到的结果可能就20个doc id,然后根据doc id到hbase里去查询每个doc id对应的完整的数据,给查出来,再返回给前端。
(2)数据预热
es集群中每个机器写入的数据量还是超过了filesystem cache一倍,
最好做一个专门的缓存预热子系统,
就是将系统经常会被搜索的数据,每隔一段时间,你就提前访问一下,让数据进入filesystem cache里面去。
(3)冷热分离
假设你有6台机器,2个索引,一个放冷数据,一个放热数据,每个索引3个shard
3台机器放热数据index;另外3台机器放冷数据index。
你大量的时候是在访问热数据index,热数据可能就占总数据量的10%,此时数据量很少,几乎全都保留在filesystem cache里面了,就可以确保热数据的访问性能是很高的。
但是对于冷数据而言,是在别的index里的,跟热数据index都不再相同的机器上。
如果有人访问冷数据,可能大量数据是在磁盘上的,此时性能差点,就10%的人去访问冷数据;90%的人在访问热数据。
(4)document模型设计
es里面的复杂的关联查询,复杂的查询语法,尽量别用,一旦用了性能一般都不太好。
document模型设计是非常重要的,很多操作,不要在搜索的时候才想去执行各种复杂的乱七八糟的操作。
es能支持的操作就是那么多,不要考虑用es做一些它不好操作的事情。
如果真的有那种操作,尽量在document模型设计的时候,写入的时候就完成。
另外对于一些太复杂的操作,比如join,nested,parent-child搜索都要尽量避免,性能都很差的。
比如:如果要做order 与 orderItem的join操作,
最好在写入es的java系统里,就完成关联,将关联好的数据直接写入es中,
搜索的时候,就不需要利用es的搜索语法去完成join来搜索了。
总之,两点:
1)在写入数据的时候,就设计好模型,加几个字段,把处理好的数据写入加的字段里面
2)自己用java程序封装,es能做的,用es来做,搜索出来的数据,在java程序里面去做,比如说我们,基于es,用java封装一些特别复杂的操作
(5)分页性能优化
es的分页是较坑的,为啥呢?
假如你每页是10条数据,你现在要查询第100页,实际上是会把每个shard上存储的前1000条数据都查到一个协调节点上,如果你有个5个shard,那么就有5000条数据,接着协调节点对这5000条数据进行一些合并、处理,再获取到最终第100页的10条数据。
你翻页的时候,翻的越深,每个shard返回的数据就越多,而且协调节点处理的时间越长。
用es作分页,很可能会发生这种现象:前几页就几十毫秒,翻到10页之后,几十页的时候,基本上就要5~10秒才能查出来一页数据了。
解决方法:
a、不允许深度分页
b、如果不是那种允许随意跳转到某页的那种分页,而是手机上那种(下拉刷微博)只能往下一页翻的那种分页,可以用scroll api。
无论翻多少页,性能基本上都是毫秒级的。
scroll的原理实际上是保留一个数据快照,然后在一定时间内,你如果不断的滑动往后翻页的时候,类似于你现在在浏览微博,不断往下刷新翻页。
那么就用scroll不断通过游标获取下一页数据,这个性能是很高的,比es实际翻页要好的多的多。
scroll是要保留一段时间内的数据快照的,你需要确保用户不会持续不断翻页翻几个小时。
os cache,操作系统的缓存