统计去重后的数量 | Elasticsearch: 权威指南

Elastic · · 148 次点击 · · 开始浏览    

速度优化edit

如果想要获得唯一值的数目, 通常 需要查询整个数据集合(或几乎所有数据)。 所有基于所有数据的操作都必须迅速,原因是显然的。 HyperLogLog 的速度已经很快了,它只是简单的对数据做哈希以及一些位操作。

但如果速度对我们至关重要,可以做进一步的优化。 因为 HLL 只需要字段内容的哈希值,我们可以在索引时就预先计算好。 就能在查询时跳过哈希计算然后将哈希值从 fielddata 直接加载出来。

预先计算哈希值只对内容很长或者基数很高的字段有用,计算这些字段的哈希值的消耗在查询时是无法忽略的。

尽管数值字段的哈希计算是非常快速的,存储它们的原始值通常需要同样(或更少)的内存空间。这对低基数的字符串字段同样适用,Elasticsearch 的内部优化能够保证每个唯一值只计算一次哈希。

基本上说,预先计算并不能保证所有的字段都更快,它只对那些具有高基数和/或者内容很长的字符串字段有作用。需要记住的是,预计算只是简单的将查询消耗的时间提前转移到索引时,并非没有任何代价,区别在于你可以选择在 什么时候 做这件事,要么在索引时,要么在查询时。

要想这么做,我们需要为数据增加一个新的多值字段。我们先删除索引,再增加一个包括哈希值字段的映射,然后重新索引:

DELETE /cars/

PUT /cars/
{
  "mappings": {
    "transactions": {
      "properties": {
        "color": {
          "type": "string",
          "fields": {
            "hash": {
              "type": "murmur3" 
            }
          }
        }
      }
    }
  }
}

POST /cars/transactions/_bulk
{ "index": {}}
{ "price" : 10000, "color" : "red", "make" : "honda", "sold" : "2014-10-28" }
{ "index": {}}
{ "price" : 20000, "color" : "red", "make" : "honda", "sold" : "2014-11-05" }
{ "index": {}}
{ "price" : 30000, "color" : "green", "make" : "ford", "sold" : "2014-05-18" }
{ "index": {}}
{ "price" : 15000, "color" : "blue", "make" : "toyota", "sold" : "2014-07-02" }
{ "index": {}}
{ "price" : 12000, "color" : "green", "make" : "toyota", "sold" : "2014-08-19" }
{ "index": {}}
{ "price" : 20000, "color" : "red", "make" : "honda", "sold" : "2014-11-05" }
{ "index": {}}
{ "price" : 80000, "color" : "red", "make" : "bmw", "sold" : "2014-01-01" }
{ "index": {}}
{ "price" : 25000, "color" : "blue", "make" : "ford", "sold" : "2014-02-12" }

多值字段的类型是 murmur3 ,这是一个哈希函数。

现在当我们执行聚合时,我们使用 color.hash 字段而不是 color 字段:

GET /cars/transactions/_search
{
    "size" : 0,
    "aggs" : {
        "distinct_colors" : {
            "cardinality" : {
              "field" : "color.hash" 
            }
        }
    }
}

注意我们指定的是哈希过的多值字段,而不是原始字段。

现在 cardinality 度量会读取 "color.hash" 里的值(预先计算的哈希值),取代动态计算原始值的哈希。

单个文档节省的时间是非常少的,但是如果你聚合一亿数据,每个字段多花费 10 纳秒的时间,那么在每次查询时都会额外增加 1 秒,如果我们要在非常大量的数据里面使用 cardinality ,我们可以权衡使用预计算的意义,是否需要提前计算 hash,从而在查询时获得更好的性能,做一些性能测试来检验预计算哈希是否适用于你的应用场景。。

本文来自:Elastic

感谢作者:Elastic

查看原文:统计去重后的数量 | Elasticsearch: 权威指南

148 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传