|
Elasticsearch搜索调优权威指南,是QBox在其博客上发布的系列文章之一,本文是该系列的第三篇,主要从凑整时间查询、全局序列号预热和文件系统缓存预热几个方面介绍了优化查询性能的一些方法。此前还发布了 Elasticsearch性能调优权威指南和Elasticsearch索引性能优化两个系列。作者:Adam Vanderbush译者:杨振涛本文是QBox官方博客“Elasticsearch搜索调优权威指南”系列文章3篇中的第3篇,第1篇参考这里,第2篇参考这里。本系列教程旨在进一步探讨针对Elasticsearch 5.0及以上版本的搜索调优技术、策略和建议。1“凑整”(Rounded)日期查询使用 now 的日期类型字段上的查询,通常不能缓存,因为匹配的范围一直在变化;但是如果转换为一个凑整的日期,就用户体验而言一般可以接受,而且通过使用查询缓存能使体验更好。以下列查询为例:curl -XPUT 'ES_HOST:ES_PORT/index/type/1pretty' -H 'Content-Type: application/json' -d '{
"my_date": "2016-05-11T16:30:55.328Z"
}'
curl -XGET 'ES_HOST:ES_PORT/index/_searchpretty' -H 'Content-Type: application/json' -d '{
"query": {
"constant_score": {
"filter": {
"range": {
"my_date": {
"gte": "now-1h",
"lte": "now"
}
}
}
}
}
}'可以替换为以下查询:curl -XGET 'ES_HOST:ES_PORT/index/_searchpretty' -H 'Content-Type: application/json' -d '{
"query": {
"constant_score": {
"filter": {
"range": {
"my_date": {
"gte": "now-1h/m",
"lte": "now/m"
}
}
}
}
}
}'在这个例子中我们凑整到分钟,因此如果当前时间是16:31:29,范围查询将会匹配my_data字段值在15:31:00到16:31:59的所有文档。如果多个用户在同一分钟内执行包含此范围的查询,查询缓存就会起到一些加速作用。凑整所使用的间隔越长,查询缓存的帮助就越大,但要注意,太大粒度的凑整也可能伤害用户体验。把范围切分成一个较大的可缓存部分,和一些较小的不可缓存部分,就能支持查询缓存,如下所示:curl -XGET 'ES_HOST:ES_PORT/index/_searchpretty' -H 'Content-Type: application/json' -d '{
"query": {
"constant_score": {
"filter": {
"bool": {
"should": [
{
"range": {
"my_date": {
"gte": "now-1h",
"lte": "now-1h/m"
}
}
},
{
"range": {
"my_date": {
"gt": "now-1h/m",
"lt": "now/m"
}
}
},
{
"range": {
"my_date": {
"gte": "now/m",
"lte": "now"
}
}
}
]
}
}
}
}
}'然而,这种实践可能会让查询在某些情况下运行得更慢,因为布尔查询的开销可能抵消了通过更好地利用查询缓存所带来的节省。2全局序列号预热Elasticsearch 默认是延迟加载属性数据到内存中的。Elasticsearch 首次遇到一个需要指定字段数据的查询时,将会为索引中的每个段加载整个属性到内存中。对于较小的段来说,只需要微不足道的时间。但是如果有5 GB的段,并且需要加载10 GB的属性数据到内存,就可能需要消耗数十秒的时间。习惯了秒级响应时间的用户,可能会忽然遭遇一个明显无法响应的网站。有三种方法来降低这种延迟峰值:预加载属性数据预加载全局序列号预热缓存数据这些都是同一个概念的变体:预加载属性数据,这样在用户需要执行检索时就没有延迟峰值。注意:序列号仅仅是为 string 类型构建和使用。数值型数据(integer、geopoint、date等)并不需要一个序列映射,因为它们自身及其属性值就是一个天然的序列映射。全局序列号是一个数据结构,用于在 keyword 类型的属性上执行term聚合。它们是延迟加载到内存中的,因为 Elasticsearch 不知道哪个属性会用于 term 聚合以及哪个属性不会。我们可以告知 Elasticsearch,通过配置下文描述的映射,来预加载全局序列号:curl -XPUT 'ES_HOST:ES_PORT/indexpretty' -H 'Content-Type: application/json' -d '{
"mappings": {
"type": {
"properties": {
"foo": {
"type": "keyword",
"eager_global_ordinals": true
}
}
}
}
}'预编译全局序列号在数据的实时性方面会有一些牺牲。对于基数非常高的属性,构建全局序列号能延迟刷新数秒钟。需要权衡的是,是在每次刷新时付出代价,还是在一次刷新后的首次查询时;如果是索引频繁而查询较少,最好选择在每次查询时,而不是在每次刷新时。我们可以让全局序列号为自身付出代价。如果有很高基数的属性,需要耗费数秒钟来重建,那么增加 refresh_interval 可以让全局序列号长期有效。这也会降低 CPU 使用率,因为需要重建全局序列号的频率会更低。3文件系统缓存预热Elasticserch 默认是完全依赖于操作系统的文件系统缓存来缓存 I/O 操作的。可以通过设置 index.store.preload 来告诉操作系统,加载热门索引文件的内容到内存中并打开。这个设置支持一个逗号分隔的文件扩展名列表:所有扩展名在该列表中的文件,将会被预加载并打开。这对于提升一个索引库的检索性能来说非常有用,特别是当主机操作系统重启时,因为这可能引发文件系统缓存失效。注意,这可能会拖慢索引的打开速度,因为它们只会在数据加载到物理内存后才可用。这个设置只是尽力而为,而且可能根本不会工作,主要取决于存储类型和主机操作系统。静态配置项 index.store.preload可以在 config/elasticsearch.yml 中设置:index.store.preload: ["nvd", "dvd"]也可以在索引创建时针对索引库设置:curl -XPUT 'ES_HOST:ES_PORT/my_index' -d ‘{
"settings": {
"index.store.preload": ["nvd", "dvd"]
}
}’其默认值是一个空数组,表示不会预加载任何数据到文件系统缓存。对于频繁搜索的索引,可能希望设置其值为 ["nvd", "dvd"],这将会触发 norms 和 doc value 预加载到物理内存。这是两个可见的一级扩展,因为 Elasticsearch 在它们上面执行随机访问。如果运行 Elasticsearch 的机器重启,文件系统缓存将被清空,所以在操作加载索引热数据到内存之前将会消耗一些时间,以便搜索操作更快。很有必要明确地告诉操作系统,哪些文件应当预加载到内存,这取决于使用 index.store.preload 设置的文件扩展。如果文件系统缓存大小不足以负担所有数据的话,将大量索引或大量文件的数据预加载到文件系统缓存,将会使检索更慢。对于比内存还大的索引来说,这个选择很危险,因为可能引发文件系统缓存被屏蔽,并在大的合并后重新打开,较大的合并会使索引和检索变慢,要谨慎使用。英文原文链接:https://qbox.io/blog/authoritative-elasticsearch-search-tuning-part-3扫码添加2020Labs小助手为好友,备注search拉入搜索引擎与NLP技术交流群!
|
|