Elasticsearch中keyword和numeric对性能的影响分析java
初学者认为这两个关键字的没啥关系,一个是用于字符串的精确匹配查询,一个是数字类型的字段用在计数的场景,好比说博客的点赞数,订单金额等。mysql
可是有些场景彷佛两个关键字均可以用,好比电商场景下的订单状态,通常咱们也是用数字表示不一样的状态,好比1表示待支付,2表示支付成功。第一反应是用Byte(属于numeric),没有问题。可是用keyword是否能够呢?sql
numeric除了支持等值精确查询,还能够范围查询。可是大部分状况下咱们业务场景对于订单状态的使用都是精确查询的,不会有大于某个状态或者小于某个状态这样的状况。微信

因此刚才说的订单状态的场景,用keyword和numeric确定均可以知足。可是那种方案好呢?答案是keyword。数据结构
对于keyword类型的term query,ES使用的是倒排索引。可是numeric类型为了能有效的支持范围查询,它的存储结构并非倒排索引。app
咱们知道倒排索引在内存里维护了词典 (Term Dictionary)和文档列表(Postings List)的映射关系,倒排索引自己对于精确匹配查询是很是快的,直接从字典表找到term,而后就直接找到了posting list。post
numeric类型从lucene6.0开始,使用了一种名为block KD tree
的存储结构。性能
Block KD tree介绍
kd-tree(k-dimensional树的简称),是一种对k维空间中的实例点进行存储以便对其进行快速检索的树形数据结构。这种存储结构相似于mysql里的B+数,咱们知道B+数这种数据结构对于范围查找的支持是很是好的。不一样于mysql, Block KD tree的叶子节点存储的是一组值的集合(block),大概是512~1024个值一组。这也是为何叫block kd tree。flex
Block KD tree对于范围查询,邻近搜索支持的很是好,尤为是多维空间的状况下。spa
看上图,每一个节点有三个元素,因此这里K=3,不一样于简单二叉树每一个节点都是一个元素(以下面这个图)。这样就能够方便的在一个三维的空间进行范围的比较。
标准的二叉树
对于上图中的kd-tree,搜索的过程是这样的:首先和根节点比较第一项,小于往左,大于往右,第二层比较第二项,依次类推。每层参与比较的数据是不同的。
具体的ES内部(实际上是Lucene),目前的版本是基于所谓的PointValues
,好比整型在Lucene内部是IntPoint
类表示,还有DoublePoint
等,完整的对应关系是:
Java type Lucene classint IntPointlong LongPointfloat FloatPointdouble DoublePointbyte[] BinaryPoint
而这些PointValues是基于kd-tree存储的,根据官方文档的介绍,lucene把叶子节点在磁盘是顺序存储的,这样搜索的效率就会很是高。
为啥numeric对于term精确匹配的查询性能没有keyword好
前面咱们提到了IntPoint
类,这个类有三个查询方法:
//构造精确查询,内部仍是调用newRangeQueryQuery newExactQuery(String field, int value)
//构造一维查询,内部是调用多维查询的方法Query newRangeQuery(String field, int lowerValue, int upperValue)
//构造多维查询Query newRangeQuery(String field, int[] lowerValue, int[] upperValue)
IntPoint.java
好比咱们有这样一个索引:
PUT blogs { "mappings": { "properties": { "title": { "type": "keyword" }, "content": { "type": "text" }, "status": { "type": "integer" } } }}
若是咱们基于status查询,
{ "query": { "term": { "title": { "status": 2 } } }}
在lucene内部其实仍是进行了一个2~2的范围查询。即使kd-tree的性能也很高,可是对于这种精确查询仍是要到树上走一遭,而倒排索引至关因而直接在内存里就定位到告终果集的文档id。若是是bool组合查询的话,term还能够利用跳表,这点numeric字段也是作不到的。
多维查询的newRangeQuery
里面是调用了PointRangeQuery
类的查询方法。
引用:
•https://www.elastic.co/cn/blog/searching-numb3rs-in-5.0
本文分享自微信公众号 - 犀牛饲养员的技术笔记(coder_start_up)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。