Elasticsearch搜索调优权威指南 (2/3)
英文原文:https://qbox.io/blog/elasticsearch-search-tuning-part-2
作者:Adam Vanderbush
译者:杨振涛
目录
- 预索引数据
- 映射
- 避免使用脚本
- 强制合并只读索引
Elasticsearch搜索调优权威指南,是QBOX在其博客上发布的系列文章之一,本文是该系列的第二篇,主要介绍了索引预处理、mapping建立、避免脚本的使用、索引段合并等搜索性能相关的调优方法。
本文是Elasticsearch搜索调优系列文章3篇中的第2篇,第1篇参考这里(点击)。本系列教程旨在更进一步讨论针对Elasticsearch 5.0及以上版本的搜索调优技术、策略及建议。
1.预索引数据
为了优化数据的索引方式,应当在查询中预置一些模式。比如,如果所有文档都有一个叫 price 的价格字段,并且大部分查询在一个固定范围列表上执行 range 聚合,那么就可以通过预索引范围到索引中并使用一个 terms 聚合,来加速该聚合。
比如有如下文档:
curl -XPUT 'ES_HOST:ES_PORT/index/type/1 ?pretty' -H 'Content-Type: application/json' -d '{ "designation": "bowl", "price": 13 }'
以及如下搜索请求:
curl -XGET 'ES_HOST:ES_PORT/index/_search ?pretty' -H 'Content-Type: application/json' -d '{ "aggs": { "price_ranges": { "range": { "field": "price", "ranges": [ { "to": 10 }, { "from": 10, "to": 100 }, { "from": 100 } ] } } } }'
然后就可以在索引阶段增加一个 price_range 字段,该字段应该映射为一个关键字:
curl -XPUT 'ES_HOST:ES_PORT/index ?pretty' -H 'Content-Type: application/json' -d '{ "mappings": { "type": { "properties": { "price_range": { "type": "keyword" } } } } }' curl -XPUT 'ES_HOST:ES_PORT/index/type/1 ?pretty' -H 'Content-Type: application/json' -d '{ "designation": "bowl", "price": 13, "price_range": "10-100" }'
接下来搜索请求就能聚合这个新的字段,而不是在 price 字段上执行一个范围聚合。
curl -XGET 'ES_HOST:ES_PORT/index/_search ?pretty' -H 'Content-Type: application/json' -d '{ "aggs": { "price_ranges": { "terms": { "field": "price_range" } } } }'
2.映射
事实上,一些数值型的数据,并不意味着总是要被映射为一个数值型字段。典型的,那些存储为诸如 ISBN 之类的标识符,或者任何标识另一个数据库中记录的数字的字段,可能映射为关键字比映射为一个 integer 或 long 类型更好。
关键字类型用于索引结构化内容,比如 email 地址、主机名称、状态码、邮政编码或标签。
典型地用于过滤(比如查找所有已发布的博客文章)、排序以及聚合。关键字字段只可通过其精确值搜索得到。
如果需要索引全文内容比如 email 内容或产品描述,可能就要使用一个文本字段。
下面是一个关键字字段映射的示例:
curl -XPUT 'ES_HOST:ES_PORT/my_index ?pretty' -H 'Content-Type: application/json' -d '{ "mappings": { "my_type": { "properties": { "tags": { "type": "keyword" } } } } }'
从 2.x 版本导入的索引是不支持关键字的;相反,它们会试图把 keyword 类型降级为 string 类型。这支持合并新的映射和旧的映射。长期存在的索引,必须在升级到6.x 版本前重建,但是映射降级提供了按自己的计划实施重建的机会。
3.避免使用脚本
一般来说要尽量避免使用脚本;如果必须要使用,优先选择 Painless 和表达式引擎。
Painless 是一门简单安全的脚本语言,专门为在 Elasticsearch 中使用而设计,是 Elasticsearch 的默认脚本语言,可安全地用于内联和存储脚本。关于 Painless 语法和语言特性的更详细描述,请参考 Painless 语言规范。
请参考 “ Painless Scripting in Elasticsearch ” 更深入地了解 Painless 脚本语言指南。
- Lucene 表达式语言
Lucene 表达式会把一个 javascript 表达式编译为字节码,设计用于高性能自定义评级和排序函数,并支持 inline 和默认的存储脚本。
- 性能
表达式相对于自定义 Lucene 代码而言,有着更好的性能表现;其性能相对其他脚本引擎有更低的单文档成本:表达式更加“领先”。
这就允许非常快的执行,尤其是比自己写的本地脚本快很多。
- 语法
表达式支持一个 javascript 语法子集:一个单独的表达式。参见表达式模块的文档,了解支持的操作符和函数。
表达式脚本中可访问的变量有:
文档字段,比如doc['myfield'].value
字段所支持的变量和方法,比如doc['myfield'].empty
传递到脚本里的参数,比如mymodifier
当前文档得分,_score(仅在 script_score中使用时有效)
表达式脚本可以用于script_score、script_fields、排序脚本以及数值型聚合脚本,只要简单地设置参数到表达式中即可。
4.强制合并只读索引
只读索引在合并为单一的段后将会非常受益。典型的情况是基于时间的索引:只有当前时间窗的索引会成为新文档,同时旧索引成为只读。
强制合并 API 支持通过 API 强制合并一个或更多的索引。合并与每个分片中 Lucene索引的段数量有关。强制合并操作支持通过合并来减少段数量。
该调用在合并完成之前将会处于阻塞状态。如果 http 连接断掉,请求将在后台继续,在前一个强制合并完成之前,所有新请求将会阻塞。
curl _XPOST 'ES_HOST:ES_POST/twitter/_forcemer ge?pretty'
强制合并 API 接受下列请求参数:
max_num_segments - 待合并的段数量。要完全合并索引,可设置为 1 。默认会简单检查一个合并是否需要执行,如果是,就会执行。
only_expunge_deletes -合并流程是否仅仅擦除包含删除的段。在 Lucene 中,一个文档并不会从一个段直接删除,只是标记为删除。在一个段合并的过程中,一个新的段可能会被创建,这个新的段并不包含那些删除。这个标记参数支持只合并有删除的段,且默认为false。注意,这并不会重写阈值 index.merge.policy.expunge_deletes_allowed。
- flush - 强制合并后是否执行 flush,默认为 true。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
突破Java面试(14)-分布式搜索引擎的架构
以下用ES表Elastic Search 0 Github 1 面试题 说说ES的分布式架构原理 2 考点分析 在搜索这块,曾经lucene 是最流行的搜索库.几年前业内一般都问,你了解 lucene 吗?你知道倒排索引的原理吗?但现在不问了,因为现在项目基本都是采用基于 lucene 的分布式搜索引擎—— ElasticSearch. 现在分布式搜索基本已经成为互联网系统的标配,其中尤为流行的就是 ES,前几年一般用 solr。但是最近基本大部分企业和项目都开始转向 ES. 所以互联网面试,肯定会跟你聊聊分布式搜索引擎,就一定会聊到ES! 如果面试官问你第一个问题,确实一般都会问你 es 的分布式架构设计能介绍一下么?就看看你对分布式搜索引擎架构的一个基本理解。 3 详解 ES的设计理念就是分布式搜索引擎,底层其实还是基于 lucene 的.核心思
- 下一篇
MaxCompute 费用暴涨之新增SQL分区裁剪失败
现象:因业务需求新增了SQL任务,这SQL扫描的表为分区表,且SQL条件里表只指定了一个分区,按指定的分区来看数据量并不大,但是SQL的费用非常高。费用比预想的结果相差几倍甚至10倍以上。 若只知道总体费用暴涨,但是没明确是什么任务暴涨,可以可以参考查看账单详情-使用记录文档,找出费用异常的记录。 分析:我们先明确MaxCompute SQL后付费的计费公式:一条SQL执行的费用=扫描输入量 ️ SQL复杂度 ️ 0.3(¥/GB)。 变量主要是输入量和复杂度,但实际上复杂度最高也就为4,由复杂度引起的费用暴涨是比较罕见,我们不妨先把排查重点放在输入量上。 排查:查看Logview的inputs信息 如上图会发现input的分区量是14个,这个与预想的(SQL条件中只指定一个分区)不一致。问题就出在这里,此时基本可以判断这个SQL的分区
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Hadoop3单机部署,实现最简伪集群
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果