正排索引、倒排索引(含实战案例)
1.正排索引与倒排索引
1.1 正排索引(Forward Index)
正排索引是一种从 文档 ID 到 文档内容 的映射结构,它存储了文档的原始数据。
特点:
- 文档 ID → 文档内容
- 类似于传统数据库的行存储
- 适合通过文档 ID 快速获取完整文档内容
示例:
文档ID: 1 → { "title": "Elasticsearch Guide", "content": "Elasticsearch is a search engine", "author": "John" }
文档ID: 2 → { "title": "Big Data", "content": "Big data is a large volume of data", "author": "Alice" }
正排索引的主要使用场景
- 获取搜索结果的具体内容
- 场景:显示搜索结果列表
- 示例:返回搜索到的前 10 篇文章的标题和摘要
- 原理:通过文档 ID 从正排索引获取原始字段值
- 排序和脚本计算
- 场景:按字段值排序或计算
- 示例:按价格排序商品,或计算折扣价
- 原理:需要访问字段原始值进行计算
- 高亮显示
- 场景:显示搜索关键词的上下文
- 示例:在搜索结果中高亮显示匹配的关键词
- 原理:需要知道字段原始内容和词项位置信息
- 字段值聚合
- 场景:基于字段值的统计分析
- 示例:计算平均价格、价格区间分布
- 原理:需要访问字段的原始数值
1.2 倒排索引(Inverted Index)
倒排索引是一种从 词项 到 文档 ID 的映射结构,是搜索引擎的核心数据结构。
特点:
- 词项 → 文档 ID 列表
- 支持快速查找包含特定词项的文档
- 包含词频、位置等信息
示例:
"elasticsearch" → [1](出现在文档 1)
"search" → [1]
"big" → [2]
"data" → [2]
"engine" → [1]
"guide" → [1]
倒排索引的主要使用场景
- 全文搜索
- 场景:用户输入关键词搜索内容
- 示例:电商平台搜索 “
无线蓝牙耳机
” - 原理:倒排索引快速定位包含这些关键词的商品
- 精确值查询
- 场景:查找特定值的文档
- 示例:查找
status=active
的用户 - 原理:倒排索引直接定位具有该精确值的文档
- 多条件组合查询
- 场景:复杂过滤和搜索
- 示例:搜索 “
价格低于 500 元且评分 4 星以上的手机
” - 原理:倒排索引高效合并多个条件的文档 ID 集合
- 聚合分析
- 场景:基于词项的统计分析
- 示例:统计最常出现的错误日志关键词
- 原理:倒排索引已经组织好了词项与文档的关系
1.3 区别对比
特性 | 正排索引 | 倒排索引 |
---|---|---|
映射方向 | 文档 ID → 文档内容 | 词项 → 文档 ID 列表 |
主要用途 | 获取完整文档内容 | 快速查找包含词项的文档 |
存储内容 | 原始文档数据 | 分词后的词项及位置信息 |
查询效率 | 通过 ID 查询快 | 全文检索快 |
更新代价 | 高(需要重建索引) | 高(需要重新计算词项映射) |
典型应用 | 获取搜索结果的具体内容 | 执行搜索查询 |
1.4 实际应用中的协同工作示例
- 搜索阶段:使用倒排索引快速找到匹配的文档 ID。
- 获取阶段:使用正排索引获取匹配文档的完整内容。
例如搜索 search engine
:
- 倒排索引找到
search
匹配文档1
,engine
匹配文档1
→ 结果[1]
。 - 正排索引获取文档
1
的完整内容返回给用户。
这种组合使得 Elasticsearch 既能高效搜索又能快速返回完整文档内容。
电商搜索案例:
- 用户搜索 “
男士 运动鞋 耐克
”(使用倒排索引快速定位匹配商品) - 系统需要:
- 按价格排序(使用正排索引获取价格字段)
- 显示商品图片、名称、价格(使用正排索引获取这些字段)
- 高亮搜索关键词(结合倒排索引的位置信息和正排索引的原始内容)
1.5 性能优化考虑
- 禁用正排索引:对于不用于排序、聚合或脚本的字段,可以设置
"doc_values": false
节省空间。 - 字段数据加载:正排索引数据在首次用于聚合 / 排序时需要加载到内存,可能影响性能。
- 存储策略:
_source
字段存储完整文档(类似正排索引),而倒排索引只存储分析后的词项。
理解这两种索引的不同用途,可以帮助我们更好地设计 Elasticsearch 的映射和查询,优化搜索性能和资源使用。
2.Kibana 实际操作案例
下面我将通过一个完整的电商商品搜索案例,演示如何在 Kibana 中实际操作并观察两种索引的工作方式。
2.1 案例准备:创建商品索引
2.1.1 创建索引并定义映射
在 Kibana Dev Tools 中执行:
PUT /products
{
"mappings": {
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": { "type": "keyword" }
}
},
"description": { "type": "text" },
"price": { "type": "double" },
"stock": { "type": "integer" },
"brand": {
"type": "keyword",
"doc_values": false // 特意关闭正排索引
},
"tags": { "type": "keyword" },
"created_at": { "type": "date" }
}
}
}
2.1.2 插入测试数据
POST /products/_bulk
{"index":{}}
{"name":"Wireless Bluetooth Headphones","description":"High-quality wireless headphones with noise cancellation","price":199.99,"stock":50,"brand":"Sony","tags":["electronics","audio"],"created_at":"2023-01-15"}
{"index":{}}
{"name":"Running Shoes Men","description":"Lightweight running shoes for men, size 9-12","price":89.99,"stock":120,"brand":"Nike","tags":["sport","footwear"],"created_at":"2023-02-20"}
{"index":{}}
{"name":"Smart Watch Pro","description":"Waterproof smartwatch with heart rate monitor","price":259.99,"stock":30,"brand":"Apple","tags":["electronics","wearable"],"created_at":"2023-03-10"}
2.2 实际操作演示
2.2.1 场景 1:倒排索引应用(全文搜索)
GET /products/_search
{
"query": {
"match": {
"description": "wireless waterproof"
}
}
}
观察点:
- 倒排索引快速找到包含
wireless
或waterproof
的文档。 - 结果会包含耳机和智能手表,但相关性更高的会排在前面。
2.2.2 场景 2:正排索引应用(排序与字段获取)
GET /products/_search
{
"query": {
"match_all": {}
},
"sort": [
{ "price": "asc" }
],
"_source": ["name", "price"],
"size": 2
}
观察点:
- 使用正排索引获取
price
字段值进行排序。 - 只返回
name
和price
字段(从正排索引获取)。
2.2.3 场景 3:倒排+正排结合(聚合分析)
GET /products/_search
{
"size": 0,
"aggs": {
"price_stats": {
"stats": { "field": "price" } // 需要正排索引
},
"popular_tags": {
"terms": { "field": "tags" } // 使用倒排索引
}
}
}
观察点:
price_stats
聚合需要正排索引计算统计值。popular_tags
聚合直接使用倒排索引的词项频率。
2.2.4 场景 4:禁用正排索引的影响
GET /products/_search
{
"query": {
"term": {
"brand": "Nike"
}
}
}
// 尝试按 brand 排序会报错
GET /products/_search
{
"sort": [
{ "brand": "asc" }
]
}
观察点:
- 搜索可以工作(使用倒排索引)。
- 排序失败因为
brand
字段设置了"doc_values": false
。
2.3 使用 Kibana Discover 验证
- 打开 Kibana → Discover
- 选择
products
索引模式 - 尝试不同搜索:
-
搜索框输入
waterproof
(倒排索引)
-
点击
price
字段的排序箭头(正排索引)
-
点击
tags
字段查看热门值(倒排索引)
-
2.4 性能对比实验
2.4.1 倒排索引效率测试
GET /products/_search
{
"query": {
"term": {
"tags.keyword": "electronics"
}
}
}
2.4.2 正排索引效率测试
GET /products/_search
{
"query": {
"range": {
"price": {
"gte": 100
}
}
}
}
对比观察:
- 在 Kibana 的右侧可以查看请求耗时。
- 大数据量时差异会更明显。
这个案例完整展示了两种索引在实际查询中的不同应用场景。