标签:ref tips ide ast 工程 agg 比较 梳理 采集
题记最近知识星球里几个问题都问到了 doc values、store field、fielddata 等的概念。
问题1:”群主有介绍 doc value, field data, store fields 比较好的文章么?一直感觉有点模糊“
问题2:“请教下星主关于ES存储相关的问题, 一个文档有如下几个地方可能会存储:
倒排索引。
Source 字段。
store 存储(如果开启)
- doc_values。
不知道我理解的是否正确?
如果这几个地方都存储, 那是不是可以理解为数据大致会膨胀了4倍?
死磕 Elasticsearch 知识星球(http://t.cn/RmwM3N9)
非常有必要好好梳理一下,于是就有了这篇文章。
Elasticsearch 数据结构的理解和合理使用,对深入理解 Elasticsearch大有裨益!
正如 Elastic 官方文档所说:
Elasticsearch 特点之一是:分布式文档存储。
Elasticsearch不会将信息存储为类似列数据库的行(row),而是存储为已序列化为JSON文档的复杂数据结构。
当集群中有多个Elasticsearch节点时,存储的文档会分布在整个集群中,并且可以从任何节点立即访问。
存储文档后,将在1秒钟内(默认刷新频率为1s)几乎实时地对其进行索引和完全搜索。
Elasticsearch使用倒排索引的数据结构,该结构支持非常快速的全文本搜索。
倒排索引列出了出现在任何文档中的每个唯一单词,并标识了每个单词出现的所有文档。
索引可以认为是文档的优化集合,每个文档都是字段的集合,这些字段是包含数据的键值对。
默认情况下,Elasticsearch 对每个字段中的所有数据建立索引,并且每个索引字段都具有专用的优化数据结构。
例如,文本字段存储在倒排索引中,数字字段和地理字段存储在BKD树中。
不同字段具有属于自己字段类型的特定优化数据结构,并具备快速响应返回搜索结果的能力使得 Elasticsearch 搜索飞快!
面对海量内容,如何快速的找到包含用户查询词的内容,倒排索引扮演了关键角色。
倒排索引是单词到文档映射关系的最佳实现形式。
下图是:书的末页的索引结构,展示了核心关键词与书页码的对应关系。
试想一下,没有这个索引页,根据关键词从全书查找有多慢,就能直观体会出索引的妙处!
拿官方文档的示例:
假设我们有两个文档,每个文档的 content 域包含如下内容:
- 1、The quick brown fox jumped over the lazy dog
- 2、Quick brown foxes leap over lazy dogs in summer
对索引编制索引会受到标记化和标准化的处理analysis。
数据索引化制约因素:分词器 analyzer 的选型。
倒排索引(基于 默认Standard 标准分词器分词)如下所示:
如上所示,对于文档中的每个词,都包含了其所在文档的列表。
默认开启
在 Elasticsearch 中,Doc Values 就是一种列式存储结构,默认情况下每个字段的 Doc Values 都是激活的(除了 text 类型),Doc Values 是在索引时创建的,当字段索引时,Elasticsearch 为了能够快速检索,会把字段的值加入倒排索引中,同时它也会存储该字段的 Doc Values。
区别于倒排索引的定义,Doc Values 被定义为:“正排索引”。
仍然 以 1.2 文档为例,Doc Values 结构如下所示(仅做举例):
Doc values 通过转置两者间的关系来解决适用倒排索引聚合效率低、难以扩展的问题。
对比可以看出:倒排索引将词项映射到包含它们的文档,doc values 将文档映射到它们包含的词项。
Elasticsearch 中的 Doc Values 常被应用到以下场景:
对于不需要:排序、聚合、脚本计算、地理位置过滤的业务场景,可以考虑禁用:Doc Values,以节约存储。
PUT my_index
{
"mappings": {
"properties": {
"title": {
"type": "keyword",
"doc_values": false
}
}
}
}
如前第1、2小结所述:
严格意义讲,2.2 的示例,放到这里会更合适。
DELETE test_001
PUT test_001
{
"mappings": {
"properties": {
"body":{
"type":"text",
"analyzer": "standard",
"fielddata": true
}
}
}
}
POST test_001/_bulk
{"index":{"_id":1}}
{"body":"The quick brown fox jumped over the lazy dog"}
{"index":{"_id":2}}
{"body":"Quick brown foxes leap over lazy dogs in summer"}
GET test_001/_search
{
"size": 0,
"query": {
"match": {
"body": "brown"
}
},
"aggs": {
"popular_terms": {
"terms": {
"field": "body"
}
}
}
}
默认情况下被禁用(构建它们很昂贵,并且在堆中预置)
text类型:聚合、排序、脚本计算
_source 字段包含在索引时间传递的原始JSON文档主体。
_source 字段本身未构建索引(因此不可搜索),但已存储该字段,以便在执行获取请求(如get或search)时可以将其返回。
第一:尽管非常方便,但是source字段确实会导致索引内的存储开销。因此,可以将其禁用。
PUT my-index-000001
{
"mappings": {
"_source": {
"enabled": false
}
}
}
第二:禁用前要做好以下衡量 禁用 _source 后,如下操作将不可用:
update, update_by_query 和 reindex API
高亮操作
所以,要在存储空间、业务场景之间权衡利弊后选型。
默认情况下,对字段值进行索引以使其可搜索(第1节的 倒排索引),但不存储它们。
这意味着可以查询该字段,但是无法检索原始字段值。
通常这无关紧要。该字段值已经是_source字段的一部分,默认情况下已存储。
但,某些特殊场景下,如果你只想检索单个字段或几个字段的值,而不是整个_source的值,则可以使用源过滤来实现。
这个时候, store 就派上用场了。
DELETE news-000001
PUT news-000001
{
"mappings": {
"_source": {
"enabled": false
},
"properties": {
"title": {
"type": "text",
"store": true
},
"date": {
"type": "date",
"store": true
},
"content": {
"type": "text"
}
}
}
}
PUT news-000001/_doc/1
{
"title": "Some short title",
"date": "2021-01-01",
"content": "A very long content field..."
}
GET news-000001/_search
GET news-000001/_search
{
"stored_fields": [ "title", "date" ]
}
如 5.2 示例,在某些情况下,存储字段可能很有意义。例如,采集的新闻数据是:带有标题、日期和很大内容字段的文档,
则可能只想检索标题和日期,而不必从较大的_source字段中提取这些字段。
回到文章开头的两个问题:
干货 | Elasticsearch 开发实战常用命令清单
你的 Elasticsearch 难题,官方文档早就有了答案......
干货 | Elasticsearch开发人员最佳实战指南
Elasticsearch 开发运维实战核心 Tips
干货 | 论Elasticsearch数据建模的重要性
干货 | Elasticsearch 索引设计实战指南
干货 | Elasticsearch多表关联设计指南
更短时间更快习得更多干货!
中国40%+Elastic认证工程师出自于此!
标签:ref tips ide ast 工程 agg 比较 梳理 采集
原文地址:https://blog.51cto.com/15050720/2562560