自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(348)
  • 资源 (1)
  • 收藏
  • 关注

原创 【lucene】DocIdSetIterator

`DocIdSetIterator` 是一个只进(forward-only)迭代器,用于遍历满足某条件的 docId 列表,支持 `nextDoc()`、`advance(target)` 等方法,广泛用于查询、过滤、缓存等场景。`int docID()` 返回当前迭代到的 docId,未开始时为 `-1`,结束为 `NO_MORE_DOCS`(即 `Integer.MAX_VALUE`)`int nextDoc()` 移动到下一个 docId,返回新的 docId 或 `NO_MORE_DOCS`

2025-07-28 10:07:29 241

原创 【lucene】BlockMaxConjunctionScore

它基于 Block-Max WAND(BMW)算法,可以提前跳过不具竞争力的文档块(block),从而显著减少倒排表的解码和打分开销。> `BlockMaxConjunctionScorer` 是 Lucene 8.5+ 对多条件 AND 查询的 Top-K 优化利器,通过 block-max 上界 + 提前跳过 技术,大幅减少不必要的倒排解码与打分,显著提升性能。- 如果当前 doc 的 maxScore < minCompetitiveScore − 其他子句 maxScore,则该 doc 被跳过。

2025-07-28 10:01:34 132

原创 【lucene】向量搜索底层文件关系梳理

下面用“一张图 + 两条流程”把 **`.vec` / `.vem` / `.vex`** 三件套以及 **HNSW vs 暴力搜索** 时如何配合这三个文件彻底讲清。- **HNSW** 用三件套做“跳读”,**暴力搜索** 跳过 `.vex` 直接扫 `.vec`,但都靠 `.vem` 快速定位向量。- **`.vec`** 是“仓库”,**`.vem`** 是“索引目录”,**`.vex`** 是“楼层导航图”。4. **无图参与**:**不读 `.vex`**,顺序读 `.vec`。

2025-07-27 22:07:26 256

原创 MMAP 机制通俗易懂

`address_space->a_ops->readpage` 把 a.dat 的 0 号 4 KiB 交给块层 → DMA 读进 **Page Cache**。- 页被标记 **DIRTY**,kswapd/内核后台线程或 `msync()` 通过 `writepage` 写回磁盘。// 设置 R/W 位。- 用户 `*(int*)p = 0x1234` → 直接改 **Page Cache**。- 同一页再被读 → MMU 直接命中,**0 次系统调用**,**0 次拷贝**。

2025-07-27 17:40:15 732

原创 mmap机制

这些都是 **NIO** 包里的 API,因此 **mmap 是 NIO 的一种实现手段**,但不是 NIO 的全部(NIO 还有 FileChannel、SocketChannel、Selector 等)。进程调用 `mmap` 后,内核立刻给它划一块**连续的虚拟地址范围**(比如 1 GB 文件就映射 1 GB 的虚拟地址),**此时并不真正吃物理内存**。- **mmap 不是零拷贝**:数据仍可能在**内核页缓存 ↔ 用户缓冲区**之间发生 CPU 拷贝(比如你 `memcpy` 到别处)。

2025-07-27 16:43:10 269

原创 零拷贝 详述

1. “零拷贝” ≠ 绝对 0 次拷贝,而是 **把原本 3~4 次的拷贝减到 1 次甚至 0 次**。- 数据从磁盘/网卡到内存这一步(DMA 进页缓存)是**不可避免的**。- 真正要省的是 **“CPU 在用户空间与内核空间之间来回搬运”** 的那几次 memcpy。2. **每一次经过 CPU 的 memcpy 都要占用 CPU 周期、寄存器、缓存行**。- DMA 搬运时 CPU 可以去做别的事。- 因此“减少拷贝”≈“减少 CPU 参与”≈“降低 CPU 开销”。

2025-07-27 16:32:08 428

原创 【lucene】MMapDirectory 在FSDirectory基础上干了啥?

最终都会走到 `SegmentCoreReaders` → `openInput(name, IOContext.READONCE / RANDOM / MERGE)` 去为每个段文件(`.cfs`, `.fdx`, `.tim`, `.doc`, …)创建 `IndexInput`。)感知不到,只是底层 `IndexInput` 实现不同。- 可插拔的 `FSIndexOutput`/`FSIndexInput` 实现(用 `FileChannel.read/write` 做真正的 I/O)

2025-07-27 15:14:19 167

原创 【lucene】SegmentReader初始化过程概述

这一步对 **每一个涉及的索引文件**(`.tim/.tip/.doc/.fdt/.fdx/.dim/.dvd/.vex/.vec…| **读取所有倒排表、doc values、stored fields 内容** | ❌ **按需 lazily** |- **数据主体**(倒排表、BKD 块、向量、stored fields 内容)**仍懒加载**,不会一次性读空磁盘。| **把整个文件内容拷贝到内存** | ❌ **不会** || `.fdt/.fdx` | ✅ 文件头 | ✅ | ❌ |

2025-07-27 02:06:12 159

原创 【lucene】Geo 数据文件是否会合并到cfs文件

在 Lucene 9.12.0 中,**Geo 数据(`.dim` / `.dii` 系列文件)以及 DocValues(`.dvd` / `.dvm` 系列文件)** **不会** 被合并进 `.cfs`(Compound File System)文件,而是 **始终作为独立文件存在**。| `.tim` / `.tip` / `.doc` / `.fdt` / `.nvd` 等 | ✅ 会 || `.dim` / `.dii`(Geo/Point) | ❌ 不会 |- `.tip`(词典索引)

2025-07-27 01:23:53 207

原创 【lucene]hnsw 向量索引文件格式说明

这些文件**始终独立存在**,不会被合并进 `.cfs`,以便支持 mmap 和高效跳读。| `.vem` | **HNSW 元数据**(维度、连接数、度量方式等) || `.vex` | **HNSW 图结构数据**(邻居连接、层级信息) || `.vec` | 原始向量数据(Flat 索引基础) || `.veq` | 量化后的向量数据(如 int8) || `.vemf` | Flat 索引的元数据 || `.vemq` | 量化索引的元数据 || 文件类型 | 作用 |

2025-07-27 01:22:14 82

原创 【lucene】不用indexSearcher可以自定义实现评分吗?

Lucene 的评分逻辑是内建在 `IndexSearcher`、`Weight`、`Scorer`、`Similarity` 这套框架里的;| 3️⃣ 遍历文档并打分 | 逐文档调 `Scorer.score()` 取得分值 | `Scorer.iterator()` + `Scorer.score()` |`Scorer` 自带一个 `DocIdSetIterator`;| 3 | 遍历文档并调用 `Scorer.score()` | `Scorer.iterator()` |

2025-07-27 00:44:55 502

原创 【lucene】仅使用IndexReader来实现搜索功能代码案例

/ 全局 docId(可选)// System.out.println("内容: " + doc.get("content"));System.out.println("全局 DocId: " + globalDocId);System.out.println("路径: " + doc.get("path"));// 2. 遍历所有段(LeafReaderContext)// 5. 遍历匹配的文档。// 4. 查找关键词是否存在。// 3. 获取字段的倒排表。// 1. 打开索引。

2025-07-26 19:07:19 204

原创 org.apache.lucene.search.Query#rewrite(IndexSearcher)过时讲解

**`IndexSearcher` 是面向用户的高级接口,Lucene 对其进行了大量优化,适合直接使用;Lucene 对 `IndexSearcher` 做了大量优化,使其更适合用户直接使用,而 `IndexReader` 则需要用户对底层实现有更深入的了解。**`IndexSearcher` 是面向用户的高级接口**,而 **`IndexReader` 是面向底层实现的低级接口**。#### 2️⃣ **`IndexReader` 是面向底层实现的低级接口**- **封装了索引的高级功能**

2025-07-26 17:49:35 394

原创 访问者模式感悟

访问者模式 首先有两个东西:一个是访问者vistor (每一个访问者类都代表了一类操作)一个是被访问者entity (model /info/pojo/node等等这些都行)也就是是说是一个实体类 其操作方法被抽离给了其他类。访问者模式的核心思想就是**“把操作从数据结构中分离出来,每种操作独立成一个访问者类”**,这样可以灵活地扩展操作,而无需修改数据结构本身。虽然是访问者提供行为本身 但是 使用时 是被访问者来调用这个方法。ta访问者模式确实是由。

2025-07-26 17:11:00 466

原创 访问者模式

访问者模式(Visitor Pattern)一句话记忆:> **“把** **对数据结构的操作** **从** **数据结构本身** **中分离出来,让同一批元素可以接受不同的‘访问者’来执行不同的行为。”**---### 🧩 场景类比想象一个 **动物园**:- **元素**:狮子、老虎、大象 …(它们是数据结构里的节点)- **访问者**:- **饲养员**(喂食)- **兽医**(体检)- **游客**(拍照)> 动物(元素)不需要知道“谁来干什么”,

2025-07-26 16:06:40 409

原创 【lucene】AttributeSource概述

`AttributeSource` 是 Lucene 的“零拷贝属性仓库”,让 TokenStream 链里的所有组件共享同一份 Attribute 实例,实现高效、低 GC 的流式分词。`OffsetAttribute` `OffsetAttributeImpl` 起始/结束偏移。`TypeAttribute` `TypeAttributeImpl` token 类型。整个链共享 `termAtt` / `offAtt`,无需拷贝。3. 使用示例(自定义 TokenFilter)

2025-07-25 13:58:39 324

原创 【lucene】如何给StandardAnalyzer添加charfilter

结论先行:不能直接给 `StandardAnalyzer` 本身加 CharFilter,因为 `StandardAnalyzer` 是 final 类,其 `createComponents` 方法只返回固定的 `Tokenizer + TokenFilter` 链,且没有预留 CharFilter 的入口。> 想给 `StandardAnalyzer` 加 CharFilter,只能 继承 Analyzer 并自己实现 `initReader`;`StandardAnalyzer` 本身不可扩展。

2025-07-25 12:04:40 322

原创 【lucene】自定义tokenfilter 自带payload

只要在自定义 `TokenFilter` 里给 `PayloadAttribute` 赋值,并在 FieldType 里打开 `setStoreTermVectorPayloads(true)`,就能把任意二进制/字符串 payload 跟每个分词一起存进索引,再通过 `TermsEnum/PostingsEnum` 原样读出。整段代码 零依赖(除了 lucene-core、lucene-analysis-common),直接 `main` 方法即可跑。// 简单规则:名词/动词/其它。

2025-07-25 10:55:20 581

原创 【lucene】高亮案例

只要 字段存储原文并开启 Term Vector,Lucene 8.5 用 Highlighter + QueryScorer 即可轻松实现关键字高亮,无需 ES 也能获得 `<font>` 或 `<span>` 标签效果。高亮器 `Highlighter`(普通文本) / `FastVectorHighlighter`(性能更好,但需额外配置)/* ---------- 2. 搜索 + 高亮 ---------- *//* ---------- 1. 建索引 ---------- */

2025-07-25 08:51:19 815

原创 【Lucene】文件概览

tvx/.tvd/.tvf TermVector 索引/数据 每篇文档每字段的 词、位置、偏移、payload 向量信息 高亮、ML 特征。.cfs/.cfe 复合文件/索引 把小文件合并成单个大文件 `.cfs` + 索引 `.cfe`(可选,减少句柄) 操作系统句柄紧张时启用。.fdx 存储字段索引 指向 `.fdt` 的 文档级别指针索引 快速随机访问 `.fdt`- 查词:`.tip` → `.tim` → `.doc/.pos/.pay`- 打分:`.nvd`/`nvm` + `.doc`

2025-07-24 12:28:20 177

原创 TwoPhaseIterator 两阶段验证

场景:使用 `PhraseQuery`(短语查询),它天然携带 `TwoPhaseIterator`,第一阶段通过倒排表拿到“候选文档”,第二阶段验证 词间距与顺序。System.out.println("✅ 通过二次验证 -> " + d.get("body"));System.out.println("候选文档 doc=" + doc);- 第一阶段:`approximation().nextDoc()` 只检查两词是否都出现过(倒排表)。.setSlop(1) // 允许 1 个词间距。

2025-07-23 16:33:04 283

原创 【lucene】实现knn

KnnFloatVectorQuery` 是 Lucene 用于执行最近邻搜索的查询类,它可以在一个字段中搜索与目标向量最相似的 k 个向量。- `KnnFloatVectorQuery` 的 rewrite 过程:在 rewrite 之后,`KnnFloatVectorQuery` 会变成 `DocAndScoreQuery`,它内部已经存储了符合条件的 `docId` 和 `score`。- HNSW 算法:HNSW 算法将新节点链接到 M 个最近邻,通过反向链接和修剪来保留多样性。

2025-07-23 16:11:01 378

原创 【Lucene】leafreadercontext逻辑段与segment物理磁盘段的关系

DirectoryReader` 打开后,`leaves()` 返回的每个 `LeafReaderContext` 就对应磁盘上的一个 segment。因此,`IndexReader.leaves()` 拿到的每个 LeafReaderContext 就等价于磁盘上的一个 segment,只是前者提供了 docBase 偏移、只读 API 等运行时信息,方便上层并行搜索与合并结果。概念 所在层次 含义 是否一一对应。

2025-07-23 11:26:09 254

原创 【Lucene】lucene的searcher.search查询机制

只有当你调用 `searcher.doc(docId)` 或 `IndexSearcher.doc(...)` 时,Lucene 才会根据 docId 去 stored fields 做随机读;- IndexSearcher.search(...) 在内部先创建 `Weight`、`Scorer`,再交给 Collector 遍历倒排表。真正的 `Document` 对象此时并未加载。因此,Lucene 可以在完全不取回 Document 的情况下完成一次查询,这正是它高性能的关键之一。

2025-07-23 11:01:56 359

原创 【Lucene】架构

index 写:建索引、刷盘、合并;读:读倒排、正排、向量 `IndexWriter` `IndexWriterConfig` `DirectoryReader` `LeafReader`search 查询解析、打分、排序、翻页、聚合 `IndexSearcher` `Query` `TermQuery` `BooleanQuery` `TopDocsCollector`索引流程 分词 → 写倒排 → 刷盘/合并 `IndexWriter` `Analyzer` `Document` `Field`

2025-07-22 14:11:58 335

原创 bmsimilarity的打分 调试参数

如果改成 `"constant_score"` 或 `filter` 子句,则 `_score` 全为固定值(1.0),不会调用 BM25。"title": { "type": "text" } // 默认 similarity = BM25。- 响应中每个 hit 都有 `_score` 字段,值各不相同 → 证明走了 BM25。3️⃣ 触发 BM25 打分查询(非 filter)1️⃣ 创建索引(什么都不改,就是 BM25)3. 触发 BM25 打分的查询。1. 建索引(默认 BM25)

2025-07-21 17:12:50 198

原创 【Lucene】SimScorer

`IndexSearcher` → `TermQuery$TermWeight.scorer()` → `TermScorer` → `TermScorer.score()` 内部调用 `simScorer.score(freq, norm)`。- 每个 `Similarity` 实现(如 `BM25Similarity`)都会创建自己的 `SimScorer` 子类(如 `BM25Scorer`)。其中 `K(norm)` 已经预先缓存到 `cache[]` 中,保证每次打分只做一次乘除。

2025-07-21 16:06:52 372

原创 【Elasticsearch】BM25的discount_overlaps参数

如果你使用了 同义词过滤器(synonym filter),多个同义词可能会落在 同一位置,这些 token 的 `positionIncrement=0`。> 在计算文档长度归一化因子(norm)时,是否忽略“重叠 token”(即位置增量 positionIncrement=0 的 token)。- 默认 `discount_overlaps=true` 会让这些 token 不影响文档长度,从而避免重复同义词“人为”拉长文档。✅ 配置示例(BM25)

2025-07-21 15:41:13 446

原创 【Elasticsearch】settings

节点启动时,`Environment` 会把 `elasticsearch.yml`、CLI 参数、jvm.options 等解析成一个全局的 `Settings` 实例。- 当你创建索引 `PUT /my_index` 时,如果没有显式指定 `number_of_shards`,就会用到这个全局默认值。- 此时 `my_index` 的 `number_of_replicas` 会自动取节点级的 `2`。那么最终该索引的 `Settings` 对象里就是 `5`,覆盖了全局的 `3`。

2025-07-21 15:37:20 467

原创 【Elasticsearch】IndexModule

插件扩展点 允许插件通过 `IndexModule.add*()` 方法注册:- 自定义 `Similarity`(评分算法)- 自定义 `QueryCache`- 自定义 `Directory`(存储后端)- 自定义 `IndexEventListener`- 自定义 `MergePolicy`、`Codec`、`RecoveryStateFactory` …工厂角色 创建并返回 `IndexService` 实例(见 `IndexModule.newIndexService(...)`)。

2025-07-21 10:49:25 157

原创 【Elasticsearch】IndexService

IndexService 就是“一个索引在单个节点里的运行时总管”,负责把这个索引在本节点托管的所有分片(主/副)以及它们要用到的资源、配置、线程池、缓存、监听等全部管理起来。线程池 提供 `index`, `search`, `refresh`, `flush`, `merge` 等线程池的引用,让分片任务有地方跑。> IndexService 是“索引在当前节点上的总控制台”,负责管理该索引在本节点内的所有分片、配置、线程池和缓存等资源。✅ IndexService 的核心职责(节点维度)

2025-07-21 10:45:01 300

原创 【Elasticsearch】dfsPhase

在 Elasticsearch 的查询流程中,`dfsPhase` 是为了在进行“评分”时更准确地计算全局的 term 频率(TF-IDF),它需要先在每个数据节点上执行一次本地的 DFS 操作,收集该节点上每个字段的 term 统计信息(如 docFreq、totalTermFreq),然后将这些信息回传给协调节点。`dfsPhase`(即 DFS 阶段)是在每个数据节点本地执行的,而不是在协调节点执行的。因此,`dfsPhase` 的执行主体是每个数据节点,协调节点只负责收集和合并结果。

2025-07-21 09:10:45 575

原创 `TransportService` 是 **Elasticsearch 传输层的“中枢路由器”**

** 通过 **TCP 连接** 发出去、收回来,并管理 **连接生命周期、超时、重试、压缩、流控和反压**。- **SearchTransportService** 只是对 `TransportService` 的 **薄封装**,把搜索相关的 `ACTION_NAME` 和序列化逻辑注册到 `TransportService`。| **节点间 RPC** | 发送任意 `TransportRequest`,接收 `TransportResponse`,支持同步/异步/批量。

2025-07-20 22:35:35 376

原创 `SearchTransportService` 是 **协调节点与数据节点之间“搜索子请求”通信的运输层**

SearchTransportService` 是 **协调节点与数据节点之间“搜索子请求”通信的运输层**,它把**协调节点**发出的 **查询阶段、取回阶段、DFS 阶段、滚动上下文等** 请求 **序列化并通过 TCP 发送给各个数据节点**,再把数据节点的返回结果 **反序列化后交还给协调节点**。| **结果回调** | 所有方法都是 **异步** 的,返回 `ActionListener<SearchPhaseResult>` 给协调节点。### ✅ 核心职责(8.x)| 职责 | 说明 |

2025-07-20 22:32:31 378

原创 SearchService 该类只运行在数据节点

都**只运行在数据节点**上,它们通过 **SearchTransportService** 注册的请求处理器被远程调用;- 在 **InitialSearchPhase** / **FetchSearchPhase** 等 **SearchPhase** 子类里,通过 `SearchTransportService` 的 `sendExecuteQuery`、`sendExecuteFetch` 等接口把子请求 **转发到数据节点**;

2025-07-20 22:28:43 140

原创 lucene 段 leaf” 就是 “segment(段)” 的别名。

因此,`LeafReaderContext` 中的 leaf 指的就是 “当前正在处理的这一个 segment”。`LeafReaderContext` 就是 “这个 segment 的上下文对象”。在 Lucene 里,“leaf” 就是 “segment(段)” 的别名。- 每个 segment 被封装为一个 LeafReader。- 一个完整的索引由 多个只读 segment 组成。> leaf = segment = 只读的最小索引单元。

2025-07-17 08:59:54 163

原创 Elasticsearch 线程池

**FIXED** | 固定大小线程池 | 线程数固定,队列大小也固定。| **SYSTEM_CRITICAL_READ / SYSTEM_CRITICAL_WRITE** | **FIXED** | 关键系统操作(如安全认证),独立固定线程保障 QoS。| **SCALING** | 弹性线程池 | 线程数按需创建,**空闲线程会被回收**。| **DIRECT** | 直接执行(无线程池) | 任务在当前线程中同步执行,**不切换线程**,**无队列**,**无并发限制**。

2025-07-12 20:10:28 505

原创 【Elasticsearch 】search_throttled

search_throttled` 是 Elasticsearch 中的一个 **专用线程池**,其作用是 **专门处理那些被“节流(throttled)”的索引上的搜索类请求**,例如 `count`、`search`、`suggest`、`get` 等操作。> `search_throttled` 是 Elasticsearch 为 **冻结或低优先级索引** 准备的“慢车道”线程池,**线程数只有 1,队列也很小**,目的是 **保护集群性能不被冷数据拖垮**。### ✅ 总结一句话。

2025-07-12 19:43:45 304

原创 【Elasticsearch】function_score与rescore

• 时机:各分片先用原始查询拿到 **window 内的 Top-K**(默认 10×page_size),然后只在 **这 K 个文档** 上重新算分;- 把 **phrase proximity**、**sloppy 查询** 放在 rescore 里,避免对全量文档计算。- 用 **昂贵脚本** 或 **复杂机器学习模型** 给 Top-K 做二次精排。> **function_score** 在 **第一次算分** 时就动手脚;• 性能:对 **全部命中文档** 都生效,数据量大时成本最高。

2025-07-12 18:55:19 468

原创 BKD 树(Block KD-Tree)Lucene

• 所有 `long`, `integer`, `double`, `date`, `ip`, `geo_point`, `geo_shape`, `dense_vector` 字段,**默认**就用 BKD 树存维度数据;),**不存文本倒排**。• 所有叶子块再建一个 **内存索引**(min-max 值 + 文件指针),查询时先扫内存索引→定位少量磁盘块→顺序读,几乎无随机 IO。• 每满 1024 个点就写成一个 **block**(顺序磁盘页),天然压缩 & 缓存友好。3. **支持的查询**

2025-07-12 18:42:40 388

xampp配置.doc

xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置

2018-04-25

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除