store vs docValues vs index

Elasticsearch 核心概念对比:store、docValues、index

概述

这三个概念分别对应 MySQL 中的不同功能,通过列式存储和索引优化来提升查询性能。


1. store - 字段独立存储

概念:将某个字段的数据单独存储,类似于 MySQL 的列存储,用空间换时间。

ES 配置示例

json 复制代码
{
  "properties": {
    "title": {
      "type": "text",
      "store": true    // 原始数据会单独存储
    }
  }
}

MySQL 对比

sql 复制代码
-- 传统行存储(类似 ES 的 _source)
CREATE TABLE articles (
  id INT,
  title VARCHAR(100),
  content TEXT,      -- 假设很大,10KB
  author VARCHAR(50)
);

-- 数据在磁盘上按行存储:
-- Row1: [1, "ES教程", "很长的内容...", "张三"]
-- Row2: [2, "MySQL教程", "很长的内容...", "李四"]

-- 如果 MySQL 支持列存储(类似 ES 的 store: true)
-- title 列单独存储:
-- title_store: ["ES教程", "MySQL教程", ...]
-- 主表仍然存储完整行数据

特点

  • store: true = 类似 MySQL 表中存储完整的列数据
  • store: false (默认)= 数据存在 _source 中,类似 MySQL 的行存储

2. docValues - 聚合排序优化

概念:将某个字段单独存储并建立索引,专门用于排序、聚合、脚本计算。

ES 配置示例

json 复制代码
{
  "properties": {
    "price": {
      "type": "integer",
      "doc_values": true    // 支持排序、聚合
    }
  }
}

MySQL 对比

sql 复制代码
-- MySQL 中类似于列存储引擎或聚合优化
SELECT AVG(price), MAX(price) FROM products;  -- 聚合查询
SELECT * FROM products ORDER BY price;       -- 排序查询

3. index - 搜索索引

概念 :相当于 MySQL 的 B+树索引,控制字段是否可被搜索。

ES 配置示例

json 复制代码
{
  "properties": {
    "email": {
      "type": "keyword",
      "index": true     // 可以被搜索
    },
    "internal_id": {
      "type": "keyword", 
      "index": false    // 不能被搜索,类似不建索引的列
    }
  }
}

MySQL 对比

sql 复制代码
-- MySQL 索引
CREATE TABLE users (
  id INT,
  email VARCHAR(100),
  internal_id VARCHAR(50)
);

CREATE INDEX idx_email ON users(email);  -- email 可以快速查询
-- internal_id 没有索引,查询会全表扫描

数据存储方式对比

原始数据(行式存储)

json 复制代码
Doc1: {"title": "ES教程", "price": 99, "category": "技术"}
Doc2: {"title": "MySQL教程", "price": 199, "category": "技术"}  
Doc3: {"title": "小说", "price": 29, "category": "文学"}

列式存储结果

bash 复制代码
# store: true - 为了快速获取字段值
title_store: ["ES教程", "MySQL教程", "小说"]

# doc_values: true - 为了聚合排序  
price_docvalues: [99, 199, 29]
category_docvalues: ["技术", "技术", "文学"]

关键区别:数据组织方式

store 存储(面向查询)

json 复制代码
// 按文档组织,便于快速返回
{
  "doc1_stored_fields": {"title": "ES教程"},
  "doc2_stored_fields": {"title": "MySQL教程"},
  "doc3_stored_fields": {"title": "小说"}
}

使用场景:获取搜索结果

json 复制代码
GET /books/_search
{
  "_source": false,
  "stored_fields": ["title"]
}

docValues 存储(面向计算)

bash 复制代码
# 按列组织,便于批量计算
price_column: [99, 199, 29]        # 可以快速计算平均价格
category_column: ["技术", "技术", "文学"]  # 可以快速分组统计

# 还会建立排序索引
price_sorted_index: [doc3→29, doc1→99, doc2→199]

实际应用场景

场景1:获取搜索结果的标题

json 复制代码
// 使用 store
GET /books/_search
{
  "query": {"match": {"content": "elasticsearch"}},
  "_source": false,
  "stored_fields": ["title"]    // 快速返回标题,不需要解析完整文档
}

场景2:按价格排序

json 复制代码
// 使用 docValues  
GET /books/_search
{
  "query": {"match_all": {}},
  "sort": [{"price": "asc"}]      // 利用 price 的 docValues 快速排序
}

场景3:价格统计分析

json 复制代码
// 使用 docValues
GET /books/_search
{
  "size": 0,
  "aggs": {
    "price_stats": {
      "stats": {"field": "price"}   // 利用 price 的 docValues 计算统计信息
    },
    "by_category": {
      "terms": {"field": "category"} // 利用 category 的 docValues 分组
    }
  }
}

存储格式差异

bash 复制代码
# store 存储格式(类似 JSON)
doc1_store: {"title": "ES教程"}
doc2_store: {"title": "MySQL教程"}

# docValues 存储格式(列式 + 索引)
price_docvalues:
  - values: [99, 199, 29]           # 原始值数组
  - sorted_index: [2,0,1]           # 排序索引:29,99,199
  - ordinals: [1,2,0]               # 序数映射(用于分组)

性能对比

json 复制代码
// 查询:获取1000本书的标题
// store 方式:直接读取 title 的独立存储 → 50KB
// _source 方式:读取1000个完整文档后解析 → 10MB

// 聚合:计算各类别的平均价格  
// docValues 方式:顺序扫描 category 和 price 列 → 100KB
// _source 方式:读取所有文档,逐个解析字段 → 10MB

组合使用示例

json 复制代码
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "index": true,          // 需要全文搜索
        "store": true,          // 经常在结果中返回
        "doc_values": false     // text 类型不支持聚合
      },
      "price": {
        "type": "double",
        "index": true,          // 需要范围查询
        "store": false,         // 不常单独返回
        "doc_values": true      // 需要排序和聚合
      },
      "description": {
        "type": "text",
        "index": false,         // 不需要搜索
        "store": false,         // 不需要单独返回
        "doc_values": false     // 不需要聚合
      },
      "summary": {
        "type": "text", 
        "index": true,          // 需要搜索
        "store": true,          // 搜索结果中显示摘要
        "fields": {
          "length": {
            "type": "integer",
            "store": false,     // 长度值不需要单独返回
            "doc_values": true  // 但需要按长度排序/统计
          }
        }
      }
    }
  }
}

内存使用差异

bash 复制代码
# store 只在查询时加载到内存
GET /books/_search → 临时加载需要的 stored_fields

# docValues 可能会被缓存在内存中(用于频繁的聚合排序)
# 但也可以直接从磁盘读取,内存压力更小

总结对比表

ES 概念 MySQL 对应 主要作用 适用场景
store 单列数据存储 单独存储字段原始值 频繁返回的字段
docValues 列存储 + 聚合索引 支持排序、聚合、脚本 需要统计分析的字段
index B+树索引 支持搜索查询 需要搜索的字段

通过合理配置这三个参数,可以在存储空间、查询性能和内存使用之间找到最佳平衡点。

相关推荐
2025学习3 小时前
Spring循环依赖导致Bean无法正确初始化
后端
l0sgAi3 小时前
最新SpringAI 1.0.0正式版-实现流式对话应用
后端
parade岁月3 小时前
从浏览器存储到web项目中鉴权的简单分析
前端·后端
用户91453633083914 小时前
ThreadLocal详解:线程私有变量的正确使用姿势
后端
IT_10244 小时前
SpringBoot扩展——发送邮件!
java·spring boot·后端
用户4099322502124 小时前
如何在FastAPI中实现权限隔离并让用户乖乖听话?
后端·ai编程·trae
阿星AI工作室4 小时前
n8n教程:5分钟部署+自动生AI日报并写入飞书多维表格
前端·人工智能·后端
郝同学的测开笔记4 小时前
深入理解 kubectl port-forward:快速调试 Kubernetes 服务的利器
后端·kubernetes
像污秽一样5 小时前
软件开发新技术复习
java·spring boot·后端·rabbitmq·cloud