为什么在Elasticsearch中需要“存储”:“是”?


69

我真的不明白为什么在核心类型链接中它会在属性描述中说(例如,对于一个数字):

  1. store-设置为yes,将实际字段存储在索引中,否,则不存储它。默认为no(请注意,JSON文档本身已存储,可以从中检索
  2. index-如果不应为该值建立索引,则设置为no。在这种情况下,应该将store设置为yes,因为如果未对它进行索引和存储,则与它无关

这两个大胆的部分似乎矛盾。如果"index":"no", "store":"no"我仍然可以从源头获得价值。例如,如果我有一个包含URL的字段,这可能是一个好用法。没有?

我做了一个小实验,在其中有两个映射,在一个域中将 "store":"yes""store":"no"

在两种情况下,我仍然可以在查询中指定:

{"query":{"match_all":{}}, "fields":["my_test_field"]}

我得到了相同的答案,返回了现场。

我认为,如果"store"设置为该值,"no"则意味着我无法撤退特定领域,但必须获得全部_source并在客户端进行解析。

那么,什么好处是在有设置"store""yes"?仅当我从"_source"字段中明确排除该字段时,才有意义吗?

Answers:


110

我认为,如果将“ store”设置为“ no”,则意味着我无法检索特定字段,而必须获取整个_source并在客户端进行解析。

当未存储字段(默认)并且_source启用该字段(也是默认值)时,这就是elasticsearch为您所做的。

您通常将字段发送到elasticsearch,因为您要在其上搜索或检索它。但是,的确,如果您不显式存储字段并且不禁用源,则仍然可以使用_source。这意味着在某些情况下,具有未索引或未存储的字段实际上可能有意义。

当您存储字段时,这是在底层的lucene中完成的。Lucene是一个倒排索引,它允许快速的全文本搜索并在给定文本查询的情况下返回文档ID。除倒排索引外,Lucene还具有某种存储方式,可以在其中存储字段值,以便在给定文档ID的情况下进行检索。通常,您要将要返回的字段存储在lucene中作为搜索结果。Elasticsearch不需要存储要返回的每个字段,因为默认情况下它始终存储您发送给它的每个文档,因此,它始终能够返回您发送给它的所有内容作为搜索结果。

仅在少数情况下,将字段显式存储在lucene中可能会很有用:_source禁用字段时,或者当我们希望避免对其进行解析时,即使解析是由Elasticsearch自动完成的。请记住,尽管从Lucene检索许多存储的字段可能需要每个字段一个磁盘查找,而_source仅从Lucene检索并解析它以检索所需的字段只是单个磁盘查找,并且在大多数情况下更快。


2
太好了!感谢您的解释。
eran 2013年

2
“请记住,尽管从lucene检索许多存储的字段可能需要每个字段一个磁盘查找,而仅从lucene检索_source并对其进行解析以检索所需的字段只是一个磁盘查找,并且在大多数情况下都更快。案件。” 给定SSD用于存储索引,查找次数减少的影响是否显着?“在HDD中,这通常在0.2到0.8毫秒之间。典型的SSD的寻道时间在0.08到0.16毫秒之间。”
阿列克谢·蒂加列夫

4
显式存储_source中未返回的字段也很有用。时间戳就是一个例子。即使您在类型上启用了它们,也将无法检索它们(“ fields”:[“ _timestamp”]将不返回任何内容),除非您在其中输入了“ _timestamp”:{“ store”:true}您对该类型的映射。
csjacobs15年

ES的新手。假设我为record_id以外的所有字段设置了“ _source = false”和“ store = no”。ES会为我提供什么样的功能?我能否计算具有给定字段的记录数或生成直方图?还要别的吗?
Marsellus Wallace 2015年

我只有一个字段,通常为〜1MB,其余字段为<1KB,因此保存_source意味着需要更多的存储空间。我还在权衡_stored字段的SSD访问是否会使速度减慢到足以满足保存_source的速度。
tishma

6

默认情况下,在Elasticsearch中,将_source存储(已索引一个文档)。这意味着当您搜索时,您可以获得实际的文档来源。此外,elasticsearch将自动提取fields / objects_source并返回他们,如果你不明确的告诉它(以及可能的其他组件使用它,就像突出)。

您可以指定还存储特定字段。这意味着,该字段的数据将被存储在它自己的。这意味着,如果您请求field1(已存储),elasticsearch将识别出它已存储,并从索引中加载而不是从索引中获取_source(假设已启用_source)。

您何时要启用存储特定字段?大多数时候,你没有。提取_source的速度很快,提取它的速度也很快。如果您的文档非常大,则存储的_source成本_source很高,或者解析的成本很高,则可以显式映射要存储的某些字段。

注意,检索每个存储的字段会产生成本。因此,举例来说,如果您有一个json,其中包含10个合理大小的字段,并且将所有字段映射为已存储,并要求所有字段,那么这意味着要加载每个字段(更多磁盘搜索),而不是加载_source(这是一个字段,可能已压缩)。

源链接


请不要复制粘贴了相同的答案,以多个问题(stackoverflow.com/a/38787655/466738stackoverflow.com/a/38787619/466738)。如果你觉得这些问题涉及到同样的事情,他们的标志将被封闭,一式两份(stackoverflow.com/help/duplicates
亚当·米哈利克

请注意,如果您有一个巨大的字段并且要store禁用_source,则无法访问_update该文档。
Marc'5
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.