ES5.0常用优化指南

来源:互联网 发布:抢票软件成网络黄牛 编辑:程序博客网 时间:2024/06/16 06:27
原文地址:https://qbox.io/blog/elasticsearch-5-0-general-performance-recommendations
我在“ES性能调优权威指南”一文中介绍了一些常见的优化技巧与建议,并在每一步中解释了最相关的系统配置和度量,具体
教程如下:

The Authoritative Guide to Elasticsearch Performance Tuning (Part 1)

The Authoritative Guide to Elasticsearch Performance Tuning (Part 2)

The Authoritative Guide to Elasticsearch Performance Tuning (Part 3)

本文推荐一些特定于ES5.0或以上的性能调优技术、策略和建议。

这篇文章我们将使用Qbox.io的ES,你可以通过 launch your cluster here登记,或者点击头部导航的 "Get Started" 。如果你需要设置的帮助,请参考这篇"Provisioning a Qbox Elasticsearch Cluster."

ES5.0.0是ES2.0之后十分很有意义的版本,它是Elastic Stack更广泛版本的一部分。Kibana,Logstash,Beats,Elasticsearch ——现在都是5.0版本。它是最快、最安全、最具弹性、最容易使用的ES版本,并带来了大量的增强和新特性。


避免大文档

    大文档通常是不实际的,对网络、内存使用和磁盘也造成很大的压力,即使搜索不请求_source然而 ES需要同样需要获取文档的_id,而文件系统缓存的机制使得获取字段比获取大文档的成本更高。索引这个文档会使用文档原始大小的几倍的内存。Proximity search近距离搜索(比如短语查询)和highlighting 高亮显示也变得更加昂贵,因为它们的成本直接取决于原始文档的大小。
curl -XGET 'localhost:9200/_search?pretty' -H 'Content-Type: application/json' -d '{   "query" : {       "match": { "content": "qbox" }   },   "highlight" : {       "fields" : {           "content" : {}       }   }}'

    默认http.max_context_length的值是100MB。ES会拒绝大于该值得文档。我们可以增大这个值,但是Lucene限制了该值最大是2GB。

   重新思考这个值是很有用的,例如,如果你想使得书本被搜索到并不意味着一个文档需要包含整个书的内容。使用摘要甚至是段落作为文档索引起来可能更好,然后在这些文档中有一个属性来确定它们属于哪一本书。着不仅仅是为了避免大文档,更使得搜索体验会更好。


避免抓取大结果集

ES作为一个搜索引擎使其很擅长获取最匹配的查询结果但是它并不适用于数据库领域中的工作负载,比如检索特定查询匹配的所有文档。如果需要这样做,请确保使用Scroll API。

curl -XPOST 'localhost:9200/twitter/tweet/_search?scroll=1m&pretty' -H 'Content-Type: application/json' -d '{   "size": 100,   "query": {       "match" : {           "title" : "qbox"       }   }}'

这个查询返回包含一个用于传给scroll API以获取下一批数据集的_scroll_id。

curl -XPOST 'localhost:9200/_search/scroll?pretty' -H 'Content-Type: application/json' -d '{   "scroll" : "1m",   "scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ=="}'

需要深入使用Scroll API可以参考 “Searching and Fetching Large Datasets in Elasticsearch Efficiently” 。


避免稀疏和最大密度的文档


   为了索引和存储数据,在Lucene底层的数据结构最适合于密集的数据。当所有文档都有相同的字段时。对于启用了规范的字段(默认情况下是text 字段)或启用了doc values(默认情况下是numericsdateip keyword ),这一点尤其适用。

    如果一个索引有M个文档,那么每个字段需要M个字节的存储空间,即使对于只出现在索引文档中的一小部分的字段也是如此。由于doc values有多种方式,它们可以根据字段的类型和字段存储的实际数据进行编码,但问题非常相似,因此文档值稍微复杂一些。在被替换为doc values之前,在ES使用的fielddata也受到了这个问题的影响,只是因为fielddata在磁盘上没有显式地物化字段数据,所以影响只在内存占用上。

     稀疏最显著的影响是存储需求,它还对索引速度和搜索速度产生了影响,因为这些字节对于没有字段的文档来说仍然需要在索引时写入,并且在搜索时跳过。稀疏也会影响倒排索引的效率(用于索引text/keyword字段)和维度点(用于索引geo_point 和numerics),但程度较低。

以下是一些避免稀疏的建议:


索引中避免无关数据

    我们应该避免将完全不同结构的文档放入同一个索引中,把这些文档放到不同的索引中通常更好,另外因为整体数量较少我们也可以考虑为这些小索引分配更小的分片。

    这个规则不适用于您在文档中使用了父/子关系的情况,因为该特性只支持同一索引中的文档。


规范文档结构

    如果你真的需要将不同类型的文档放入同一索引,那么这同样有一些方法减少稀疏。例如如果所有的文档有一个timestamp 字段,然而有的是timestamp 有的是creation_date,那么最好重命名一下以使得所有的文档有同样的字段。


避免使用类型

让我们考虑以下两个类型:

{   "data": {      "mappings": {         "people": {            "properties": {               "name": {                  "type": "string",               },               "address": {                  "type": "string"               }            }         },         "transactions": {            "properties": {               "timestamp": {                  "type": "date",                  "format": "strict_date_optional_time"               },               "message": {                  "type": "string"               }            }         }      }   }}

每一个类型定义了两个字段(分别是"name"/"address" and "timestamp"/"message" )。他们看起来毫不相关,但是在Lucene底层将创建一个类似下面看到的mapping:

{   "data": {      "mappings": {        "_type": {          "type": "string",          "index": "not_analyzed"        },        "name": {          "type": "string"        }        "address": {          "type": "string"        }        "timestamp": {          "type": "long"        }        "message": {          "type": "string"        }      }   }}

    这个mappings本质上被扁平化为一个单一的全局模式。这也是为什么两个类型不能定义冲突的字段:Lucene在扁平化字段后没不知道怎么办。

    类型听起来是在同一索引中存储多租户的好办法。但实际上不是:给定类型将索引内容存在一个索引,单个索引有多个类型时就会导致前面所说的稀疏性。如果类型没有很相似的mappings,那么你最好考虑将他们移动到专用的索引中。


稀疏字段上禁用Norms和Doc_Values

    如果以上的建议对你都不试用,你可能需要检查一下你是否需要norms和doc_values 在你的稀疏字段上。norms可以被禁用如果字段打分不是必须的,典型的使用场景是只对字段使用过滤。doc_values同样可以被禁用如果你不需要排序或者聚合。由于这些参数不能在实时索引中更改,所以不应该轻松地做出这个决定,因此如果你意识到需要norms或doc_values,就必须重新索引。

curl -XPUT 'localhost:9200/my_index/_mapping/my_type?pretty' -H 'Content-Type: application/json' -d '{ "properties": {   "title": {     "type": "text",     "norms": false   } }}'

    

提示:Norms 不会被立即删除,但是当你继续索引新的文档时,旧段合并为新段时将删除Norms。在一个已经有norms的字段中计算打分可能会返回不一致的结果,因为一些文档没有norms而其他文档可能又有norms。

doc values默认是true的。如果你确定不需要排序和聚合,或者通过script访问该字段,你可以禁用doc values以节省磁盘空间。

curl -XPUT 'localhost:9200/my_index?pretty' -H 'Content-Type: application/json' -d '{ "mappings": {   "my_type": {     "properties": {       "status_code": {         "type":       "keyword"       },       "session_id": {         "type":       "keyword",         "doc_values": false       }     }   } }}'
因为时间比较仓促,个人水平也有限,可能会有不少错误还望指正,如果有解释不清或错误的烦请参考原文,后续我也会重新校注,谢谢。
原创粉丝点击