This is an automated email from the ASF dual-hosted git repository.

zhangstar333 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris-website.git


The following commit(s) were added to refs/heads/master by this push:
     new a58c903b3a7 [doc](lance) update prefilter boolean param (#4203)
a58c903b3a7 is described below

commit a58c903b3a7fb3c4e3b3489b2da9645673f61fd0
Author: zhangstar333 <[email protected]>
AuthorDate: Tue Oct 13 15:54:00 2026 +0800

    [doc](lance) update prefilter boolean param (#4203)
    
    update prefilter boolean param
---
 .../lakehouse/best-practices/doris-lance.mdx       |   6 +-
 .../best-practices/lance-hybrid-search.mdx         |  18 ++-
 .../best-practices/lance-query-profile.md          | 158 +++++++++++++++++++++
 .../lakehouse/catalogs/lance-catalog.mdx           |  48 ++++---
 .../lakehouse/best-practices/doris-lance.mdx       |   6 +-
 .../best-practices/lance-hybrid-search.mdx         |  22 +--
 .../best-practices/lance-query-profile.md          | 158 +++++++++++++++++++++
 .../lakehouse/catalogs/lance-catalog.mdx           |  48 ++++---
 versioned_sidebars/version-4.x-sidebars.json       |   1 +
 9 files changed, 409 insertions(+), 56 deletions(-)

diff --git 
a/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/best-practices/doris-lance.mdx
 
b/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/best-practices/doris-lance.mdx
index b3d8c061c00..b89d84e8181 100644
--- 
a/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/best-practices/doris-lance.mdx
+++ 
b/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/best-practices/doris-lance.mdx
@@ -248,7 +248,7 @@ lance_metadata_cache_size_bytes = 1073741824
 重启该 BE 后生效。应分别为每个 BE 做预算;这些是 BE 配置参数,不是 Catalog 属性或 SQL 会话变量。
 
 1. 使用有代表性的查询及并发预热,覆盖不同查询向量、过滤条件和表。仅重复同一个查询向量会低估多样化工作负载的工作集。
-2. 对比 `doris_be_lance_session_index_cache_usage_bytes` 与 
`doris_be_lance_session_index_cache_capacity_bytes`、时间窗口内 
`hits_total`/`misses_total` 的增量,以及每次查询的 
`LanceIndexPartitionCacheMissLoads`。使用量接近容量且持续未命中,可能意味着缓存反复淘汰;新分区、新索引版本或切换 BE 
也会造成未命中。只有确认存在复用需求且内存允许时才增大容量。
+2. 对比 `doris_be_lance_session_index_cache_usage_bytes` 与 
`doris_be_lance_session_index_cache_capacity_bytes`,并观察时间窗口内 
`hits_total`/`misses_total` 的增量。对每次已完成的查询,还应查看 `LanceIndex` 下的 
`LanceIndexCacheHits`、`LanceIndexCacheMisses`、`LanceIndexObjectLoads` 和 
`LanceIndexComponentsLoaded`。查询缓存查询次数与部件加载数范围不同,均不能替代 BE 
全局指标增量。使用量接近容量且持续未命中可能意味着缓存反复淘汰,但新分区、新索引版本、切换 BE 
和不保留内容的流式路径也会造成未命中。只有确认存在复用需求且内存允许时才增大容量。
 3. BE 内存预算允许时,Metadata Cache 可从默认的 1 GiB 开始,根据其 `usage_bytes` 
和命中/未命中指标调整。文件/Fragment 数量、Schema/页面元信息、删除信息和 row ID 
映射决定其需求,不能按向量索引大小的固定比例配置。BE Metadata Cache 与 FE 表访问缓存相互独立。
 4. 增大任何一个缓存前,都应在目标并发下检查 BE 
进程内存和查询峰值。缓存命中率高但查询仍慢,可能是评分、Prefilter、解码或回表开销,增大缓存不一定有效。
 5. 单独为精排和输出列回表等重复数据文件读取配置 `lance_data_cache_disk_capacity_bytes`。增大它不会扩大 Index 
Cache,也不能弥补索引缓存未命中:索引文件绕过这个磁盘数据缓存。`lance_data_cache_read_block_size_bytes` 
建议先保持默认的 1 MiB,再根据有效读取量与读放大调整。
@@ -278,7 +278,7 @@ lance_metadata_cache_size_bytes = 1073741824
 
 Index Cache 和 Metadata Cache 容量独立:元数据条目不会直接淘汰索引条目,增大其中一个也不会扩大另一个。但两者仍消耗同一个 BE 
进程的内存。磁盘数据缓存是第三份预算,且不缓存索引文件。同一 BE 上拆分 Catalog 不能隔离 Index 
Cache;需要隔离的工作负载,应使用部署环境支持的独立 BE 资源和路由能力。
 
-排查相互抢占时,可先预热一类查询,记录延迟和缓存指标增量;再运行另一类查询,随后重复第一类查询。在索引版本和 BE 
分配具有可比性的前提下,如果接近容量时重新出现未命中或加载,说明可能存在淘汰压力。Session 命中/未命中指标汇总了多种工作负载,需要结合查询 
Profile 分析。预热所有索引本身也可能淘汰希望保留的工作集。应优先使用有代表性的混合工作负载预热,仅在有复用需求且内存允许时增大容量。
+排查相互抢占时,可先预热一类查询,记录延迟和缓存指标增量;再运行另一类查询,随后重复第一类查询。在索引版本和 BE 
分配具有可比性的前提下,如果接近容量时重新出现未命中或加载,说明可能存在淘汰压力。Session 命中/未命中指标汇总了多种工作负载,需要结合查询级 
`LanceIndexCacheHits`/`LanceIndexCacheMisses`、`LanceIndexComponentsLoaded` 和 
`LanceIOReadBytes` 
分析。部件加载数不是未命中数,执行读取字节也不是实测远端流量。预热所有索引本身也可能淘汰希望保留的工作集。应优先使用有代表性的混合工作负载预热,仅在有复用需求且内存允许时增大容量。
 
 ## 5. 选择 Index Segment 粒度 {#index-segment-granularity}
 
@@ -325,4 +325,4 @@ Segment 数应与每个 Segment 的 IVF `num_partitions`、查询 `nprobes` 一
 | 缓存未满但进程内存很高 | 并发查询分配、正在加载的数据、仍被引用的对象和其他 BE 工作负载 | 
根据测得的峰值降低并发或缓存预算;缓存容量不是进程内存上限 |
 | 数据文件 I/O 持续较高 | 磁盘缓存计数、复用情况、读取块大小和输出列 | 调整数据缓存预算或读取粒度;索引文件不使用这个磁盘数据缓存 |
 
-使用[查看缓存效果](../catalogs/lance-catalog.mdx#查看缓存效果)中的 Profile 计数器和 BE 
指标。仅凭汇总命中率无法判断哪个索引被淘汰,或哪个阶段占主要耗时。每次改变一个配置,记录每组对比的工作负载、索引版本、BE 分配、延迟、吞吐、召回率和峰值内存。
+使用[查询 Profile 参考](lance-query-profile.md)区分 FE 元数据/规划、BE 索引/扫描工作和第二阶段 Row ID 
回表;缓存计数与 BE 
全局指标见[查看缓存效果](../catalogs/lance-catalog.mdx#查看缓存效果)。仅凭汇总命中率无法判断哪个索引被淘汰,或哪个阶段占主要耗时。每次改变一个配置,记录每组对比的工作负载、索引版本、BE
 分配、延迟、吞吐、召回率和峰值内存。
diff --git 
a/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/best-practices/lance-hybrid-search.mdx
 
b/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/best-practices/lance-hybrid-search.mdx
index 2fb00d038b1..042f8ed8973 100644
--- 
a/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/best-practices/lance-hybrid-search.mdx
+++ 
b/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/best-practices/lance-hybrid-search.mdx
@@ -181,13 +181,19 @@ Lance 的[索引格式](https://lance.org/format/index/)定义逻辑索引和物
 
 | 阶段 | 证据 | 如何解释 |
 |---|---|---|
-| 规划与覆盖率 | `EXPLAIN` 中的 
`lanceSearchIndexSegments`、`lanceSearchUnindexedFragments`;Profile 中 Scanner 数 
| 确认 Split 数、回退工作量以及计划能否利用预期布局。 |
-| Prefilter | 
`LancePrefilterInputRows`、`LancePrefilterRowIds`、`LancePrefilterLoadTime`、`LancePrefilterBuildTime`
 | Load 包含构建过滤器的耗时,不应相加。没有远程 I/O 时,大 Row ID 集合仍可能主导开销。 |
-| 标量 Segment 路径 | 有统计值时的 
`LanceScalarIndexSegmentsRequested`、`LanceScalarIndexSegmentsSearched`、`LanceScalarIndexCandidateRows`
 | 这些计数描述已埋点的标量 Segment 路径,不一定覆盖 ANN/FTS 内部所有标量查询。零值不能证明没有标量过滤。 |
-| 索引加载与搜索 | 
`LanceIndexPartitionCacheMissLoads`、`LanceExecutionIOBytesRead`、`LanceIndexComparisons`,以及可用的详细索引计时器
 | 区分缓存重新加载、热缓存搜索和候选处理。I/O 计数为零不代表没有 CPU 工作。 |
-| 输出回表 | 存在时的 Materialization 算子和 Row ID Fetch 计时 | 将输出列读取与候选检索分开归因。 |
+| FE 元数据与规划 | `Execution Summary` → `Lance Metadata 
Metrics`:`MetadataReadTime`、`IndexMetadataReadTime`、`SplitPlanningTime` 及对应的 
`Calls` | 将 Catalog 元数据访问和 Split 规划与 BE 检索区分;元数据总耗时包含其子步骤。 |
+| 规划与覆盖率 | 
`EXPLAIN`:`lanceSearchIndexSegments`、`lanceSearchIndexFragments`、`lanceSearchUnindexedFragments`;`LanceSearchPlan`:`LancePlannedIndexSegmentCount`、`LancePlannedIndexedFragmentCount`、`LancePlannedFlatSearchFragmentCount`
 | 描述已规划/分配的检索工作,不代表已完成搜索;Flat Search 计数适用于向量查询,不适用于 FTS。 |
+| 读取器配置与 batch 读取 | 
`LanceTiming`:`LanceDatasetOpenTime`、`LanceScannerConfigureTime`、`LanceScannerNextTime`、`LanceArrowToDorisBlockTime`
 | 区分打开/配置、Lance 读取和 Doris 转换;batch 读取耗时包含内部搜索、I/O、解码和等待。 |
+| Row ID Prefilter | 
`LanceScan`:`RowIdPrefilterLoads`、`RowIdPrefilterInputRows`、`RowIdPrefilterInputBatches`、`RowIdPrefilterIds`、`RowIdPrefilterLoadTime`、`RowIdPrefilterInputTime`、`RowIdPrefilterBuildTime`
 | 输入等待/读取和 mask 构造属于总加载耗时;这些指标描述 Row ID 加载器,不覆盖所有标量谓词,也不是最终候选集合。 |
+| 标量 Segment 路径 | 
`LanceScalarIndex`:`LanceScalarIndexSegmentsRequested`、`LanceScalarIndexSegmentsSearched`、`LanceScalarIndexSegmentFallbacks`、`LanceScalarIndexCandidateRows`、`LanceScalarIndexCandidateEvaluationTime`、`LanceScalarIndexSegmentSearchTime`
 | 候选求值包含 Segment 搜索;候选计数早于 Fragment 限定和完整过滤,重复任务可能重复计数,基数不可得时也可能为零。 |
+| 索引复用与 I/O | 
`LanceIndex`:`LanceIndexCacheHits`、`LanceIndexCacheMisses`、`LanceIndexObjectLoads`、`LanceIndexComponentsLoaded`、`LanceIndexComparisons`;`LanceIO`:`LanceIOReadBytes`、`LanceIOReadOps`、`LanceIOReadRequests`
 | 区分对象/部件加载、缓存查询和搜索工作;加载数不是未命中数,执行 I/O 不是完整远端流量。 |
+| 向量分区选择与搜索 | 
`LanceIVFPartitionsConsidered`、`LanceIVFPartitionSelectionTime`、`LanceIndexPartitionsSearched`、`LanceVectorIndexDeltasSearched`、`LanceIndexPartitionLoadTime`、`LanceIndexSearchTime`、`LanceIndexDistanceTopKTime`
 | 区分分区选择和实际搜索;距离/Top-K 耗时包含过滤与堆操作,且与搜索耗时重叠;FTS 也报告已搜索分区。 |
+| 等待与并发 | 
`LanceIndexPrefilterWaitTime`、`LanceIndexCpuQueueWaitTime`、`LanceScanTaskWaitTime`
 | 区分索引 Prefilter 等待、CPU 任务队列等待和 FilteredRead 任务等待,均不是完整 I/O 等待或 Doris 调度总量。 |
+| 输出回表 | Row ID Fetch/Materialization 
信息:`LanceRowIdFetchCalls`、`LanceRowIdFetchRows`、`LanceRowIdFetchTotalTime`、`LanceRowIdTakeReadTime`、`LanceArrowToDorisBlockTime`
 及数据缓存字节计数 | 回表总量包含读取/转换子步骤,使用独立统计路径;不能将同一份导出值再次作为独立工作相加。 |
 | 端到端延迟 | 最慢 Scanner、依赖等待、FE 等待/取结果/写结果和客户端墙钟时间 | 不能将重叠算子或所有并行 Scanner 
的时间直接相加作为查询延迟。 |
 
-Profile 详细程度取决于 Doris 构建和内置 Lance 埋点。缺失指标不等于实测为零。`FileScannerV2` 包含 Scanner 
打开、读取和关闭工作;读取区间可能包括 Prefilter 加载、索引 I/O、运行时等待、ANN 搜索、Refine 
和转换。嵌套或并行计时不是可直接相加的分解。如果现有指标无法解释该区间,应收集 CPU/I/O Trace 
或使用带所需详细埋点的构建,再判断剩余开销是否来自存储。
+指标定义和范围见 [Lance 查询 Profile 参考](lance-query-profile.md);Dataset 数据缓存字节及 BE 全局 
Session 指标见[查看缓存效果](../catalogs/lance-catalog.mdx#查看缓存效果)。查询级索引缓存计数不是 Session 
总量的差值。
+
+Profile 详细程度取决于运行的 FE/BE 和内置 Lance 埋点。Scanner 
指标会预注册,零值也可能表示原生路径未报告指标;执行回调还要求流消费完成,因此失败、取消或提前终止的扫描可能计数不完整。不能仅凭缺失或零值就判断未使用索引或过滤。`LanceScannerNextTime`
 与内部搜索和等待计时重叠,其值较大不证明存储是瓶颈。现有指标不能解释读取区间时,应先收集 CPU/I/O Trace,再判断剩余开销是否来自存储。
 
 对无过滤条件的向量查询,如果读取器具有 Segment 范围优化,且选中的索引 Segment 完整位于扫描 Fragment 范围内,可以避免枚举所有 
Row ID。真实标量谓词仍需计算,删除和可见性处理也可能保留。对齐能减少可避免的工作,但不保证带过滤检索的 Prefilter 开销为零。
diff --git 
a/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/best-practices/lance-query-profile.md
 
b/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/best-practices/lance-query-profile.md
new file mode 100644
index 00000000000..41a012c57cd
--- /dev/null
+++ 
b/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/best-practices/lance-query-profile.md
@@ -0,0 +1,158 @@
+---
+{
+    "title": "Lance 查询 Profile 指标参考",
+    "sidebar_label": "Lance 查询 Profile",
+    "language": "zh-CN",
+    "description": "解读 Apache Doris Lance 查询 Profile:FE 元数据与规划、BE 
索引和扫描指标、缓存统计、计时边界及第二阶段 Row ID 回表。",
+    "keywords": [
+        "Lance",
+        "Query Profile",
+        "性能分析",
+        "向量检索",
+        "索引缓存"
+    ]
+}
+---
+
+本文介绍普通 Lance 扫描、向量检索、全文检索和第二阶段 Row ID 回表的 Profile 指标。Profile 的采集、查看和通用算子分析方法见 
[Query Profile 分析指南](../../query-acceleration/query-profile.md);Lance 访问配置见 
[Lance Catalog](../catalogs/lance-catalog.mdx)。
+
+:::note
+Lance Catalog 是实验性功能,从 Apache Doris 4.2 开始支持。下述指标取决于运行的 FE/BE 和内置 Lance 版本。
+:::
+
+执行 Lance 查询前开启 Profile:
+
+```sql
+SET enable_profile = true;
+```
+
+以下名称对应当前 Lance 埋点。较旧的 Doris 构建或内置 Lance 版本可能缺少部分指标,或使用旧名称。比较结果时,应查看已完成查询的 
Profile,并确认实际运行的 FE/BE 版本。
+
+## FE 元数据与规划
+
+对于 Catalog 查询,包括普通扫描、`COUNT`、向量检索和全文检索,在 `Execution Summary` 下查看 `Lance 
Metadata Metrics`:
+
+| 计时器 | 含义 |
+|---|---|
+| `MetadataReadTime` | 一次 Catalog 元数据读取的总耗时,包含表访问解析、Dataset 访问和资源清理。 |
+| `TableAccessResolveTime` | 解析表访问,包括 Namespace 访问、凭证和存储选项。 |
+| `DatasetOpenTime` | FE 打开 Dataset 的耗时,历史查询可能需要多次打开。 |
+| `VersionResolveTime` | 在需要时解析目标历史快照。 |
+| `SchemaReadTime` | 读取 Arrow Schema。 |
+| `FragmentMetadataReadTime` | 读取 Fragment 元数据并构造行数描述。 |
+| `FieldIdsReadTime` | 读取并映射 Lance field ID。 |
+| `IndexMetadataReadTime` | 发现逻辑索引并读取 Index Segment 元数据。 |
+| `SplitPlanningTime` | 规划普通扫描、元数据 COUNT、向量检索或全文检索的 Split。 |
+
+已执行的操作或步骤还会生成对应的 `Calls` 计数,例如 `DatasetOpenCalls`。`MetadataReadFailures` 和 
`SplitPlanningFailures` 表示失败操作次数,失败操作的耗时也会记录;它们不是失败 SQL 
数量。未执行的元数据步骤不生成计数器。本组累计同一条 SQL 中不同表和重复读取的 Catalog 工作;独立文件 TVF 和 `SHOW INDEX` 
不产生本组统计。
+
+`MetadataReadTime` 包含元数据子步骤,`SplitPlanningTime` 单独计时。通用的 `External Table Get 
Table Meta Time`、`External Table Get File Scan Tasks Time` 和 `External Table 
Meta Time` 已包含相应工作,不应再与 Lance 细分计时或外层分析/规划时间相加。FE 的 `DatasetOpenTime` 与 BE 的 
`LanceDatasetOpenTime` 分属不同进程。
+
+## BE 分组与统计边界
+
+在扫描 Profile 中查找 `TableReader` → `LanceReader`。其下的分组是标签,不是计时器;分组层级不表示子项耗时可以相加。
+
+| 分组 | 内容 |
+|---|---|
+| `LanceTiming` | Dataset 打开、Scanner 配置和读取、Runtime Filter 转换、Arrow 转换及 Row ID 
回表。 |
+| `LanceIO` | 已埋点执行流的读取操作数、请求数和字节数。 |
+| `LanceIndex` | 索引对象/内部部件加载、缓存查询、比较、索引打开和已搜索分区。 |
+| `LanceVectorIndex` | IVF 分区选择、向量索引 delta、ANN 阶段及向量距离计算。 |
+| `LanceScalarIndex` | 标量索引求值、Segment 搜索、候选、回退和结果序列化。 |
+| `LanceExecutionPlan` | Lance 执行计划中的排序、归并和 Take 工作。 |
+| `LanceScan` | Fragment/行范围/行数扫描、读取任务等待和 Row ID Prefilter 构造。 |
+| `LanceSearchPlan` | 分配给读取器的检索 Segment/Fragment 数。 |
+| `LanceDataCache` | Dataset handle 的数据文件缓存及源存储请求字节数。 |
+
+Doris 计时器围绕相应调用更新。Lance 执行计数在流消费到 EOF 后通过统计回调累加;失败、取消或提前终止可能导致执行统计不完整。Scanner 
指标会预注册,包括可选的原生指标:零值也可能表示原生路径没有报告该指标。不能仅凭指标缺失或为零,就判断没有使用索引、过滤或 I/O 路径。仅使用元数据的 
`COUNT` 和 Row ID 回表不经过普通 Scanner 回调路径。
+
+时间按调用和并行任务累加,可能大于 SQL 墙钟时间。应结合最慢 Scanner、调度、依赖等待、FE 结果处理和客户端耗时分析,不应累加所有 
Scanner 或嵌套计时来还原查询延迟。
+
+## 读取器计时
+
+| 计时器 | 含义 |
+|---|---|
+| `LanceDatasetOpenTime` | 通过 BE 共享 Session 打开 Dataset,包含必要的元数据访问。复用读取器中已打开的 
Dataset 时不再次计时。 |
+| `LanceScannerConfigureTime` | 配置 Scanner、投影、过滤、回调和 
Split/检索选项;延迟到读取时执行的工作在后续阶段计时。 |
+| `LanceRuntimeFilterSqlTranslationTime` | 将 Doris Runtime Filter 转换/组合为 Lance 
SQL,包括转换缓存查询;不是执行过滤的耗时。 |
+| `LanceScannerNextTime` | 累计读取 batch 的调用耗时,包含首批准备、索引计算、I/O、解码和等待,不含随后 Arrow 到 
Doris 的转换。 |
+| `LanceArrowToDorisBlockTime` | 将返回的 Arrow batch 转换为 Doris Block,扫描与 Row ID 
回表均使用此指标。 |
+
+`LanceScannerNextTime` 与下述内部索引、扫描和执行计划计时重叠,仅凭它较大不能认定存储是瓶颈。
+
+## I/O、索引加载与缓存查询
+
+| 计数器 | 含义 |
+|---|---|
+| `LanceIOReadOps` | 已埋点的读取操作数,不是每秒操作数或 HTTP 请求数。 |
+| `LanceIOReadRequests` | 已埋点的存储读取请求数;范围合并/拆分会使它与 `LanceIOReadOps` 不同。 |
+| `LanceIOReadBytes` | 
执行计划报告的读取字节数,包含已埋点的数据/索引路径;可能包含由缓存提供的读取,不是实测远端流量或解码后的内存大小。 |
+| `LanceIndexObjectLoads` | 加载的顶层索引对象数,不是 Segment 数或其内部页的加载数。 |
+| `LanceIndexComponentsLoaded` | 加载的索引内部部件数,例如页、分区或 
posting;不是索引缓存未命中计数,加载/合并与埋点差异可能使两者不同。 |
+| `LanceIndexCacheHits`、`LanceIndexCacheMisses` | 已埋点索引路径报告的本次执行缓存查询,与 BE 共享 
Session 的命中/未命中总量不同。部分流式路径不保留加载内容,因此持续未命中不能单独证明缓存容量不足。 |
+| `LanceIndexComparisons` | 各索引实现定义的比较/查找工作量,不是候选行数,也不是跨索引类型统一的 CPU 成本单位。 |
+
+这些计数适用于已埋点的向量、标量和全文索引路径。顶层索引对象可以仍在缓存中,而其页或分区需要重新加载。增大容量前,应结合缓存使用量、可复现的冷/热缓存查询及 
I/O 判断。独立磁盘数据缓存和 BE 全局指标见[查看缓存效果](../catalogs/lance-catalog.mdx#查看缓存效果)。
+
+## Row ID Prefilter 与标量索引工作
+
+Row ID Prefilter 指标描述消费 Row ID 并构造允许行 mask 的加载器,不覆盖所有 TVF 
`filter`、所有标量索引查询,也不是最终 ANN/FTS 结果数。
+
+| 计数器或计时器 | 含义 |
+|---|---|
+| `RowIdPrefilterLoads` | 实际 Row ID 加载器执行次数;重复查询节点可能重复加载。 |
+| `RowIdPrefilterInputRows`、`RowIdPrefilterInputBatches` | 加载器消费的非 null Row ID 
数和 batch 数。 |
+| `RowIdPrefilterIds` | 构造后的 mask 中保留的允许行 ID 数,按加载器累加,不是全查询去重数量。 |
+| `RowIdPrefilterLoadTime` | 加载器总耗时,包括输入轮询和 mask 构造。 |
+| `RowIdPrefilterInputTime`、`RowIdPrefilterBuildTime` | 输入流等待/读取和 mask 
构造耗时,均包含在 `RowIdPrefilterLoadTime` 中,不能把总量与子项相加。 |
+| `LanceScalarIndexQueryTime` | 标量索引表达式求值,可能包含多次索引搜索和集合运算。 |
+| `LanceScalarIndexResultSerializationTime` | 将标量索引结果序列化给下游 Lance 节点,不是网络序列化或 
Arrow 到 Doris 的转换。 |
+| `LanceScalarIndexSegmentsRequested`、`LanceScalarIndexSegmentsSearched` | 
显式标量 Segment 路径的请求次数与完成 Segment 求值的次数,属于执行计数,不是表中不同 Segment 的数量。 |
+| `LanceScalarIndexSegmentFallbacks` | 显式标量 Segment 加速回退为分配 Fragment 
范围内的完整过滤扫描;已搜索的 Segment 也可能回退。 |
+| `LanceScalarIndexCandidateRows` | 基数已知时的候选 mask 大小,在读取器限定 Fragment 
范围和应用完整谓词之前记录;不是 SQL 结果数,零值也可能表示基数不可得。 |
+| `LanceScalarIndexCandidateEvaluationTime` | 准备、求值和安装标量 Segment 
候选,包含索引打开/搜索及回退准备,不含后续数据扫描。 |
+| `LanceScalarIndexSegmentSearchTime` | 求值所选 Segment 的索引表达式,包含其加载和集合运算;已包含在 
`LanceScalarIndexCandidateEvaluationTime` 中。 |
+
+一个 Segment 可以覆盖比单个任务更多的 Fragment,重复任务也可能重复统计相同候选,因此不能把 `CandidateRows` 
当作任务范围内的命中行数。常规标量表达式路径与显式 Segment 路径使用不同计时,不要求两者值相同。热缓存下,大 mask 或重复 Segment 
求值仍可能消耗 CPU 和内存。
+
+## 向量与执行计划工作
+
+| 计数器或计时器 | 含义 |
+|---|---|
+| `LanceIVFPartitionsConsidered` | 选择分区时考虑的 IVF 分区规模,按所选索引 delta 
累加,不是实际执行的探测数。 |
+| `LanceIVFPartitionSelectionTime` | 为查询选择 IVF 分区,不含外层索引打开。 |
+| `LanceIndexPartitionsSearched` | 索引执行实际报告的分区搜索计数,FTS 也报告此指标,需结合 
`LanceSearchType` 解读;不是全查询去重分区数。 |
+| `LanceVectorIndexDeltasSearched` | 提交给 ANN 分区路径的向量索引 delta 数,不证明每个 delta 
均已完成搜索。 |
+| `LanceIndexOpenTime` | 打开索引 handle,包含缓存查询和元数据访问。 |
+| `LanceIndexPartitionLoadTime`、`LanceIndexPartitionPrepareTime` | 
分区加载包含缓存查询、缓存填充等待和未命中后的加载/解码;分区准备包含加载和过滤准备,两者计时重叠。 |
+| `LanceIndexPrefilterWaitTime` | 等待索引 Prefilter 就绪,与构建 Row ID mask 不同。 |
+| `LanceIndexCpuQueueWaitTime` | 分区搜索任务从提交到开始 CPU 工作的等待时间。 |
+| `LanceIndexSearchTime` | 已准备分区的 CPU 搜索,包含查询准备和结果构造。 |
+| `LanceIndexQueryPrepareTime` | 构造距离计算器和查询查找表。 |
+| `LanceIndexDistanceTopKTime` | 融合的候选过滤、距离计算和 Top-K 堆更新,不是纯距离计算或精排计时。 |
+| `LanceIndexResultMaterializeTime` | 将搜索结果堆转换为 Arrow 数组/batch,不是 Doris 
第二阶段输出回表。 |
+| 
`LanceANNPartitionExecTime`、`LanceANNSubIndexExecTime`、`LanceANNBatchExecTime` 
| 已埋点 ANN 执行节点的计算时间,可能与详细索引计时重叠。 |
+| `LanceVectorDistanceComputeTime` | 向量距离执行节点报告的计算耗时,不覆盖索引内部所有距离计算。 |
+| `LanceSortComputeTime`、`LanceSortMergeComputeTime`、`LanceTakeExecTime` | 
Lance 执行节点的排序、归并和 Take 计算耗时,不是 Doris TopN 或完整第二阶段回表耗时。 |
+
+分区工作并发执行,计时可以嵌套或重叠。不应将 `LanceIndexSearchTime` 与其查询准备、距离/Top-K 和结果构造子项相加。调整 
`nprobes`、`ef` 或 `refine_factor` 前,先对比分区探测数、CPU 队列等待、Prefilter 等待和 
I/O,并同时测量召回率与延迟。
+
+## 计划规模、扫描行数与输出回表
+
+| 计数器或计时器 | 含义 |
+|---|---|
+| `LancePlannedIndexSegmentCount` | 分配给读取器的检索索引 Segment 数,在配置 Split 
时累加,不证明已完成搜索。 |
+| `LancePlannedIndexedFragmentCount` | 分配给带索引的向量/全文检索 Split 的 Fragment 数。 |
+| `LancePlannedFlatSearchFragmentCount` | 分配给向量 Flat Search Split 的 Fragment 
数,FTS 不注册此计数器。 |
+| `LanceFragmentsScanned`、`LanceRowOffsetRangesScanned`、`LanceRowsScanned` | 
FilteredRead 路径报告的 Fragment 数、行偏移范围数和行数,并非所有读取路径均报告;不是全表去重数量或最终 SQL 行数。 |
+| `LanceScanTaskWaitTime` | FilteredRead 消费者等待读取任务的耗时,不是 Doris Scanner 
调度时间,也不是完整的 I/O 等待总量。 |
+| `LanceRowIdFetchCalls`、`LanceRowIdFetchRows` | 第二阶段 `take_rows` 调用次数与回读行数。 |
+| `LanceRowIdTakeReadTime` | 创建并消费 Row ID Take 流,包括延迟读取,不含 Arrow 到 Doris 的转换。 |
+| `LanceRowIdFetchTotalTime` | 非空 Row ID 回表处理总耗时,包括 Dataset 打开、Take 
读取、转换和结果校验;包含前述子步骤,不含端到端 RPC/Materialization 开销。 |
+
+检索规划可将 `EXPLAIN` 中的 
`lanceSearchIndexSegments`、`lanceSearchIndexFragments`、`lanceSearchUnindexedFragments`
 与 `LanceSearchPlan` 计数对照。普通标量 Segment 扫描应查看 
`lanceGroupingIndexSegments`、`lanceGroupingIndexedFragments`、`lanceGroupingUnindexedFragments`;它们是
 FE 计划字段,不是 BE Profile 计数器。Fragment 数按任务累加,不保证去重。
+
+两阶段回表使用单独的读取器,不注册 Scanner 执行统计回调。其回表计时、回表计数和 
`LanceDataCacheBytesReadFromCache`/`LanceDataCacheBytesReadFromRemote` 也会显示在 
Row ID Fetch/Materialization Profile 信息中。该处缺少 `LanceIOReadBytes` 不代表没有 
I/O。分析时应区分扫描和回表范围,避免重复计算同一份导出的回表统计。
+
+使用 `LanceDatasetVersion` 和 `LanceDatasetUri` 确认执行快照,使用 `LanceSearchType` 
区分向量和全文检索。`LanceTopK`、`LanceOffset`、`LanceFtsCoverageMode`、`LanceFtsQueryType`、`LanceFtsMatchOperator`、`LanceFtsMaxFuzzyDistance`、`LanceFtsPhraseSlop`、`LancePushdownFormat`
 和 Runtime Filter ID 条目描述配置或下推状态,属于信息字符串,不能作为计数器相加。`LanceTopK` 和 `LanceOffset` 
描述每个 Split 的请求:TVF 查询设为 `top_k=K`、`offset=n` 时,检索 Split 请求最多 `K+n` 个候选,局部 
offset 为 `0`;最终由 Doris TopN 应用用户 offset。
+
diff --git 
a/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/catalogs/lance-catalog.mdx
 
b/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/catalogs/lance-catalog.mdx
index 88383ab8990..199da0e385b 100644
--- 
a/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/catalogs/lance-catalog.mdx
+++ 
b/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/lakehouse/catalogs/lance-catalog.mdx
@@ -721,6 +721,7 @@ FROM vector_search(
     "metric" = "l2",
     "nprobes" = "20",
     "refine_factor" = "10",
+    "prefilter" = "true",
     "filter" = "category = 'book'",
     "use_index" = "true"
 )
@@ -749,8 +750,9 @@ ORDER BY _distance ASC, user_id;
 | `metric` | 否 | `l2` | 距离类型:`l2`、`cosine`、`dot` 或 `hamming`。`dot_product` 是 
`dot` 的别名。`uint8` 向量仅支持 `hamming`;其他当前支持的向量元素类型支持 `l2`、`cosine` 和 `dot`。查询 
`cosine`、`dot` 或 `hamming` 索引时必须显式设置 `metric`。不支持整数多向量列及多向量 `hamming` 检索。 |
 | `distance_lower_bound` | 否 | 无下界 | 单向量检索的距离下界,包含边界值,必须是有限的 `FLOAT`。 |
 | `distance_upper_bound` | 否 | 无上界 | 单向量检索的距离上界,不包含边界值,必须是有限的 
`FLOAT`。同时设置上下界时,转换为 `FLOAT` 后下界必须小于上界。 |
-| `filter` | 否 | - | Lance SQL 条件,在生成候选向量之前执行,即 Prefilter。 |
-| `nprobes` | 否 | 最少 `1`,不限制最大值 | IVF 索引探测的分区数量,必须为正整数。不设置时从 1 个分区开始;使用 
Prefilter 且候选不足时,Lance 可以继续探测更多分区。显式设置为 `N` 时,最少和最多探测数都会固定为 `N`。 |
+| `filter` | 否 | - | 由 Lance 执行的 SQL 条件。执行时机由 `prefilter` 控制。 |
+| `prefilter` | 否 | `false` | 控制 TVF `filter` 的执行时机。`true` 
表示在生成向量候选前过滤;`false`(默认值)表示在候选生成后过滤,结果可能少于 `top_k`。该参数不影响外层 Doris `WHERE`。 |
+| `nprobes` | 否 | 最少 `1`,不限制最大值 | IVF 索引探测的分区数量,必须为正整数。不设置时从 1 个分区开始;设置 
`prefilter=true` 且候选不足时,Lance 可以继续探测更多分区。显式设置为 `N` 时,最少和最多探测数都会固定为 `N`。 |
 | `refine_factor` | 否 | 单向量不启用;多向量为 `1` | 
候选集精排倍数,必须为正整数。对于单向量检索,不设置时不基于原始向量重新计算距离,量化索引返回的 `_distance` 可能是近似距离;设置为 `N` 
后,Lance 先获取 `(top_k + offset) × N` 个候选,再用原始向量计算真实距离并重新排序。**精排会读取这些候选的原始向量数据;`N` 
越大,读取和计算的候选越多,可能显著增加 I/O 并降低查询性能。** 对于单向量检索,设为 `1` 
会执行精排,与不设置不同。多向量检索始终使用原始向量精排,默认倍数为 `1`。 |
 | `ef` | 否 | `floor(1.5 × (top_k + offset))` | HNSW 
图索引搜索时保留的候选宽度,必须为正整数。如果同时设置了 `refine_factor`,默认值为 `floor(1.5 × (top_k + offset) 
× refine_factor)`。对非 HNSW 索引无效。 |
 | `use_index` | 否 | `true` | `true` 表示优先使用与向量列和距离类型兼容的 Lance 向量索引;没有可用索引时自动使用 
Flat Search。`false` 表示禁用向量索引,对数据执行 Flat Search。 |
@@ -793,7 +795,7 @@ ORDER BY _distance;
 +---------+-----------+
 ```
 
-去掉下界后还会返回第 1 行。仅设置上界为 `0` 则返回空结果。`filter` 仍在向量检索前限制候选行,`offset` 
在应用距离范围后跳过结果。输出 Schema 不变,包含表中的列和 `FLOAT` 类型的 `_distance`。`EXPLAIN` 会显示 
`lanceDistanceRange=[1.0, 4.0)`。
+去掉下界后还会返回第 1 行。仅设置上界为 `0` 则返回空结果。`prefilter=true` 时,`filter` 在向量检索前限制候选行;默认 
`prefilter=false` 时,它在候选生成后过滤。`offset` 在应用距离范围后跳过结果。输出 Schema 不变,包含表中的列和 
`FLOAT` 类型的 `_distance`。`EXPLAIN` 会显示 `lanceDistanceRange=[1.0, 4.0)`。
 
 距离边界支持预编译语句中的 `?` 参数,每次执行都会校验并使用当次绑定值,不接受 NULL。若不限制某一侧距离,请省略对应属性。
 
@@ -904,7 +906,7 @@ ORDER BY _distance, id;
 | 1 | 0.0 |
 | 2 | 2.0 |
 
-记录 1 为每个查询子向量都提供了完全匹配。记录 2 与第一个查询子向量的距离为 `0`,与第二个的平方 L2 距离为 `2`。外层为空数组或 null 
的记录不参与排名。增加 `"offset" = "1"` 并将 `"top_k" = "1"` 后,仅返回记录 2。增加 `"filter" = "id > 
1"` 会先限制候选检索的记录范围,对此数据集也仅返回记录 2。
+记录 1 为每个查询子向量都提供了完全匹配。记录 2 与第一个查询子向量的距离为 `0`,与第二个的平方 L2 距离为 `2`。外层为空数组或 null 
的记录不参与排名。增加 `"offset" = "1"` 并将 `"top_k" = "1"` 后,仅返回记录 2。增加 `"filter" = "id > 
1"` 并设置 `"prefilter" = "true"`,会先限制候选检索的记录范围;对此数据集也仅返回记录 2。
 
 #### 行级评分
 
@@ -955,7 +957,7 @@ _distance = sum(q in Q, min(v in V, distance(q, v)))
 
 索引检索的候选选择是近似的。多向量候选**始终使用原始向量精排**,包括不设置 `refine_factor` 或将其设为 `1` 
的情况,从而使有索引与无索引的记录使用相同的行级评分。增大 `refine_factor` 
会扩大候选集,增加原始向量读取和计算,但不保证完整召回。`nprobes` 控制 IVF 探测范围,`ef` 对 HNSW 
索引生效;调参时应同时测量召回率与耗时。索引创建后追加的记录会通过 Flat Search 纳入检索。
 
-如需对选定记录进行穷举评分,使用 `"use_index" = "false"`。优先使用 TVF 的 `filter` 在检索前缩小候选范围;外层 SQL 
`WHERE` 会丢弃候选,但不会补齐对应 split 的结果。下一节的过滤规则同时适用于单向量和多向量查询。
+如需对选定记录进行穷举评分,使用 `"use_index" = "false"`。需要在检索前缩小候选范围时,使用 TVF 的 `filter` 并设置 
`prefilter=true`;默认 `prefilter=false` 会在候选生成后应用该条件。外层 SQL `WHERE` 始终由 Doris 
过滤已生成的候选,不会补齐对应 split 的结果。下一节的过滤规则同时适用于单向量和多向量查询。
 
 ### Prefilter 和 Post-filter
 
@@ -968,6 +970,7 @@ FROM vector_search(
     "column" = "embedding",
     "query_vector" = "[0.1, 0.2, 0.3, 0.4]",
     "top_k" = "10",
+    "prefilter" = "true",
     "filter" = "category = 'book'"
 )
 WHERE user_id > 100
@@ -976,10 +979,11 @@ ORDER BY _distance ASC, user_id;
 
 | 过滤方式 | 示例条件 | 执行时机 | 对结果的影响 |
 |---|---|---|---|
-| Prefilter | TVF 参数 `"filter" = "category = 'book'"` | Lance 生成向量候选之前 | 只在 
`category = 'book'` 的数据中搜索最近邻。 |
-| Post-filter | 外层 `WHERE user_id > 100` | Lance 生成候选之后、Doris 执行最终 TopN 之前 | 
从已生成的候选中删除不满足条件的行,不会补充新的候选,因此最终结果可能少于 `top_k`。 |
+| TVF Prefilter | TVF 参数 `"filter" = "category = 'book'"` 且 `"prefilter" = 
"true"` | Lance 生成向量候选之前 | 只在 `category = 'book'` 的数据中搜索最近邻。 |
+| TVF Post-filter | TVF 参数 `"filter" = "category = 'book'"`,且 `prefilter` 缺省或为 
`false` | Lance 生成候选之后 | 从已生成的候选中删除不满足条件的行,不会补充新的候选,因此结果可能少于 `top_k`。 |
+| Doris Scan Post-filter | 外层 `WHERE user_id > 100` | Lance 生成候选之后、Doris 执行最终 
TopN 之前 | 从已生成的候选中删除不满足条件的行,不会补充新的候选,因此最终结果可能少于 `top_k`。 |
 
-如果 `user_id > 100` 也必须参与最近邻候选生成,应将它合并到 `filter` 中,例如 `"filter" = "category = 
'book' AND user_id > 100"`,而不是使用外层 `WHERE`。即使优化器将外层 `WHERE` 下移到 Doris 的 Lance 
Scan,它仍然是 Post-filter,不会转换成 Lance Prefilter。
+如果 `user_id > 100` 也必须参与最近邻候选生成,应将它合并到 TVF `filter` 中并设置 `prefilter=true`,例如 
`"filter" = "category = 'book' AND user_id > 100"`。如果 `prefilter` 为默认值 
`false`,该条件会在候选生成后过滤。外层 `WHERE` 即使被优化器下推到 Doris 的 Lance Scan,也仍是 Doris Scan 
Post-filter,不会转换成 Lance Prefilter。
 
 `filter` 中引用的列由 Lance 内部读取和计算;如果该列未被 `SELECT` 或其他 Doris 表达式引用,则不需要返回给 Doris。
 
@@ -1059,15 +1063,16 @@ lance_data_cache_read_block_size_bytes = 1048576
 
 ### 查看缓存效果
 
-在查询 Profile 的 `LanceReader` 下查看以下计数器:
+在已完成查询的 Profile 中,索引缓存计数位于 `LanceReader` → `LanceIndex`,数据文件缓存计数位于 
`LanceReader` → `LanceDataCache`:
 
 | 计数器 | 含义 |
 |---|---|
-| `LanceDataCacheBytesReadFromCache` | 经过数据缓存路径、命中缓存并返回给 reader 的逻辑字节数。 |
-| `LanceDataCacheBytesReadFromRemote` | 经过数据缓存路径、未命中后从源存储读取并返回给 reader 
的逻辑字节数。源存储也可以是本地文件。 |
-| `LanceIndexPartitionCacheMissLoads` | 因索引分区缓存未命中而加载的分区数,不是整个索引缓存的未命中次数。 |
+| `LanceIndexCacheHits`、`LanceIndexCacheMisses` | 已埋点索引路径报告的本次执行缓存查询,与 BE 共享 
Session 指标不同。 |
+| `LanceIndexObjectLoads`、`LanceIndexComponentsLoaded` | 
加载的顶层索引对象及内部部件数,均不能替代缓存未命中计数。 |
+| `LanceDataCacheBytesReadFromCache` | 当前 Dataset handle 的数据文件缓存提供的逻辑请求字节数。 |
+| `LanceDataCacheBytesReadFromRemote` | 缓存未命中或回退后由源存储提供的逻辑请求字节数,源存储也可以是本地文件。 |
 
-两个数据缓存字节计数不包含按块读取产生的额外字节,也不覆盖索引、manifest 等绕过数据缓存的 
I/O,因此不能用它们代替完整的远端流量统计。数据缓存关闭时,这两个计数为 `0`,不代表没有读取源存储。计数在关闭 Dataset 
时收集,应查看查询完成后的 Profile;第二阶段回读也会复用缓存,但这两个扫描计数器不能视为整个查询所有回读 I/O 的合计。
+两个数据缓存字节计数不包含按块读取的放大,也不覆盖索引、manifest 等绕过数据缓存的 I/O,因此不能代替完整的远端流量统计,两者之和也不要求等于 
`LanceIOReadBytes`。关闭数据缓存时两个计数均为 `0`,不代表没有读取源存储。Doris 在关闭 Dataset handle 
前记录其累计快照。第二阶段回表具有单独的读取器统计,并导出到 Row ID Fetch/Materialization Profile 
信息中;仅有扫描计数不能覆盖全查询的回表 I/O。采集时机和指标范围见[Lance 查询 Profile 
指标参考](../best-practices/lance-query-profile.md)。
 
 BE 的 `/metrics` 还提供以 `doris_be_lance_session_index_cache_` 和 
`doris_be_lance_session_metadata_cache_` 为前缀的指标,后缀分别为 
`capacity_bytes`、`usage_bytes`、`entries`、`hits_total` 和 
`misses_total`,表示配置容量、当前使用量、条目数、累计命中和累计未命中。这些是 BE 共享缓存指标,初始化共享 Lance Session 
后注册,不能直接归属于某一条查询。
 
@@ -1108,7 +1113,7 @@ FROM vector_search(
 WHERE category = 'book';
 ```
 
-TVF `filter` 中引用的 Prefilter 列由 Lance 在搜索内部使用,不会仅因为出现在 `filter` 
字符串中就作为第一阶段结果列返回给 Doris。
+TVF `filter` 中引用的列由 Lance 在搜索内部使用,不会仅因为出现在 `filter` 字符串中就作为第一阶段结果列返回给 
Doris;`prefilter` 只改变该条件相对候选生成的执行时机。
 
 ### 验证是否生效
 
@@ -1150,6 +1155,7 @@ FROM full_text_search(
     "operator" = "and",
     "top_k" = "10",
     "offset" = "0",
+    "prefilter" = "true",
     "filter" = "category = 'storage'",
     "coverage_mode" = "strict"
 )
@@ -1157,7 +1163,7 @@ WHERE published = true
 ORDER BY _score DESC, document_id;
 ```
 
-上例使用 Match AND,只返回同时包含分词结果 `lance` 和 `database` 的文档。`filter` 是 Lance 在生成 FTS 
候选结果前执行的 Prefilter;外层 `WHERE` 是生成候选结果后执行的 Post-filter。Post-filter 
不会补充被过滤掉的候选行,因此最终结果可能少于 `top_k`。如果 `published = true` 也必须参与候选生成,应将它合并到 `filter` 
中。
+上例使用 Match AND,只返回同时包含分词结果 `lance` 和 `database` 的文档。`prefilter=true` 时,Lance 
在生成 FTS 候选结果前执行 `filter`;缺省 `prefilter=false` 时,Lance 在候选生成后应用 `filter`,结果可能少于 
`top_k`。外层 `WHERE` 是由 Doris 执行的 Post-filter,也不会补充被过滤掉的候选行。如果 `published = true` 
必须参与候选生成,应将它合并到 `filter` 中并设置 `prefilter=true`。
 
 下面的查询使用 Phrase,并允许相邻查询词之间最多存在一个其他 token。例如,它可以匹配 `lance search engine`:
 
@@ -1188,7 +1194,8 @@ ORDER BY _score DESC, document_id;
 | `slop` | 否 | `0` | 仅用于 Phrase 查询,必须是 `0` 到 `2147483647` 之间的整数。`0` 
要求精确短语,正数表示相邻查询词之间允许存在的最大 token 数。Match 查询不能设置该参数。 |
 | `top_k` | 否 | `10` | 跳过 `offset` 后返回的结果数,必须为正整数。 |
 | `offset` | 否 | `0` | 按相关性跳过的结果数,必须为非负整数;`top_k + offset` 不能超过无符号 32 位整数的最大值。 
|
-| `filter` | 否 | - | 生成全文检索候选结果前由 Lance 执行的 SQL 条件,即 Prefilter。 |
+| `filter` | 否 | - | 由 Lance 执行的 SQL 条件。执行时机由 `prefilter` 控制。 |
+| `prefilter` | 否 | `false` | 控制 TVF `filter` 的执行时机。`true` 
表示在生成全文检索候选结果前过滤;`false`(默认值)表示在候选生成后过滤,结果可能少于 `top_k`。该参数不影响外层 Doris `WHERE`。 |
 | `coverage_mode` | 否 | `strict` | FTS 索引未覆盖当前快照全部 Fragment 时的处理方式,可选值为 
`strict` 或 `index_only`。 |
 | `version`、`timestamp`、`tag`、`branch` | 否 | - | 检索历史版本、某个时间点的版本、tag 或 
branch,而不是 main 的最新版本。见[检索历史版本或 
branch](#search-a-historical-version-or-branch)。 |
 
@@ -1266,7 +1273,8 @@ ORDER BY _score DESC;
   -> FE 规划检索 Split
        -> 向量检索:物理向量 Index Segment + 未覆盖 Fragment 的 Flat Search
        -> 全文检索:物理 FTS Index Segment(按 coverage_mode 检查覆盖情况)
-  -> 每个 Split:Lance Prefilter -> 向量/全文检索 -> 最多 K+n 个候选
+  -> 每个 Split:向量/全文检索;TVF filter 在 prefilter=true 时于候选生成前应用,缺省 false 时于候选生成后应用
+       -> 最多 K+n 个候选
   -> Doris Scan Post-filter
   -> Doris 局部 TopN
   -> Exchange
@@ -1274,6 +1282,10 @@ ORDER BY _score DESC;
   -> 可选的延迟物化 Fetch
 ```
 
+## 查询 Profile {#query-profile}
+
+Profile 的采集和查看方法见 [Query Profile 
分析指南](../../query-acceleration/query-profile.md)。Lance 专用分组、计数器、计时边界和第二阶段回表统计见 
[Lance 查询 Profile 指标参考](../best-practices/lance-query-profile.md)。
+
 ## 当前限制和建议
 
 - Lance Catalog 和 Lance TVF 当前仅支持读取,不支持 `CREATE 
TABLE`、`INSERT`、`UPDATE`、`DELETE`、`TRUNCATE TABLE` 或写回 Lance。
@@ -1285,5 +1297,5 @@ ORDER BY _score DESC;
 - 可以使用 `SHOW INDEX` 查看 Filesystem Catalog 表的 Lance 
逻辑索引,例如在执行向量或全文检索前确认索引名、索引类型和被索引字段;REST Catalog 不支持 `SHOW INDEX`。
 - 向量查询需要稳定顺序时,显式使用 `ORDER BY _distance ASC` 并增加唯一 Tie-breaker。
 - 全文查询需要稳定顺序时,显式使用 `ORDER BY _score DESC` 并增加唯一 Tie-breaker。
-- 需要在向量或全文候选生成前过滤时使用 TVF 的 `filter`;外层 `WHERE` 只过滤每个搜索 Split 已生成的候选,并在 Doris 
全局 TopN 之前执行,应允许其最终结果少于 `top_k`。
+- 需要在向量或全文候选生成前过滤时,设置 TVF 的 `filter` 和 `prefilter=true`;默认 `prefilter=false` 
时,TVF `filter` 在候选生成后应用。外层 `WHERE` 则由 Doris 过滤每个搜索 Split 已生成的候选,并在 Doris 全局 
TopN 之前执行,最终结果可能少于 `top_k`。
 - 使用 `EXPLAIN` 检查 `lanceSearchFragments` 和 
`lanceSearchIndexSegments`。前者表示固定快照中的可见 Fragment 数量,后者表示 FE 选择的物理 Index Segment 
Split 数量。向量检索还可能包含回退的 Flat Search Fragment Split;全文检索不会回退到 Flat Search。
diff --git 
a/versioned_docs/version-4.x/lakehouse/best-practices/doris-lance.mdx 
b/versioned_docs/version-4.x/lakehouse/best-practices/doris-lance.mdx
index 4cbfac6a4b5..b222f3534e1 100644
--- a/versioned_docs/version-4.x/lakehouse/best-practices/doris-lance.mdx
+++ b/versioned_docs/version-4.x/lakehouse/best-practices/doris-lance.mdx
@@ -246,7 +246,7 @@ lance_metadata_cache_size_bytes = 1073741824
 Restart that BE for these settings to take effect. Apply the budget separately 
to each BE; these are BE configuration parameters, not catalog properties or 
SQL session variables.
 
 1. Warm up with representative queries and concurrency, including different 
query vectors, filters, and tables. Repeating one vector alone understates a 
diverse workload's working set.
-2. Compare `doris_be_lance_session_index_cache_usage_bytes` with 
`doris_be_lance_session_index_cache_capacity_bytes`, the interval increases of 
`hits_total`/`misses_total`, and the per-query 
`LanceIndexPartitionCacheMissLoads`. Persistent misses with usage near capacity 
suggest cache churn; misses can also come from new partitions, index versions, 
or different BEs. Increase capacity only when reuse and available memory 
justify it.
+2. Compare `doris_be_lance_session_index_cache_usage_bytes` with 
`doris_be_lance_session_index_cache_capacity_bytes`, and observe the interval 
increases of `hits_total`/`misses_total`. For each completed query, also 
inspect `LanceIndexCacheHits`, `LanceIndexCacheMisses`, 
`LanceIndexObjectLoads`, and `LanceIndexComponentsLoaded` under `LanceIndex`. 
Query cache lookups and component loads have different scopes; they are not 
interchangeable with BE-wide metric deltas. Persistent misses with [...]
 3. Start metadata-cache sizing from the default 1 GiB when the BE memory 
budget permits. Adjust using its `usage_bytes` and hit/miss metrics. 
File/Fragment counts, schema/page metadata, deletion information, and row-ID 
mappings determine demand; it is not a fixed percentage of vector-index size. 
The BE metadata cache is separate from the FE table-access cache.
 4. Check BE process memory and query peaks under the intended concurrency 
before increasing either cache. A high cache hit rate with high latency can 
indicate scoring, Prefilter, decoding, or fetch costs; additional cache is not 
necessarily useful.
 5. Size `lance_data_cache_disk_capacity_bytes` independently for repeated 
data-file reads such as refinement and output-column fetches. Increasing it 
does not enlarge the index cache or compensate for index-cache misses: index 
files bypass this disk data cache. Keep 
`lance_data_cache_read_block_size_bytes` at its 1 MiB default initially, then 
change it only after measuring useful reads versus read amplification.
@@ -276,7 +276,7 @@ lance_metadata_cache_size_bytes = 1073741824
 
 The index and metadata caches have separate capacities: metadata entries do 
not directly evict index entries, and increasing one does not enlarge the 
other. Both still consume the same BE process memory. The disk data cache is a 
third budget and does not cache index files. Separate catalogs on the same BE 
do not provide index-cache isolation; workloads requiring isolation need 
separate BE resources and routing supported by the deployment.
 
-To diagnose contention, first warm one query family and record latency and 
cache-metric deltas. Run a second family, then repeat the first. Renewed misses 
or reloads with cache usage near capacity suggest eviction pressure, provided 
index versions and BE placement stayed comparable. Session hit/miss metrics 
aggregate workloads, so combine them with query profiles. Prewarming every 
index can itself evict the working set you wanted to retain. Prefer 
representative mixed-workload warmup, an [...]
+To diagnose contention, first warm one query family and record latency and 
cache-metric deltas. Run a second family, then repeat the first. Renewed misses 
or reloads with cache usage near capacity suggest eviction pressure, provided 
index versions and BE placement stayed comparable. Session hit/miss metrics 
aggregate workloads, so combine them with query-level 
`LanceIndexCacheHits`/`LanceIndexCacheMisses`, `LanceIndexComponentsLoaded`, 
and `LanceIOReadBytes`. Component loads are not miss [...]
 
 ## 5. Choose Index Segment Granularity {#index-segment-granularity}
 
@@ -323,4 +323,4 @@ For BTree point lookups or selective Bitmap queries, 
splitting into many segment
 | Process memory is high despite cache usage below capacity | Concurrent query 
allocations, active loads, retained objects, and other BE workloads | Lower 
concurrency or cache budgets based on measured peaks; cache capacity is not a 
process-memory cap |
 | Data-file I/O stays high | Disk-cache counters, reuse, read block size, and 
query output columns | Adjust the data-cache budget or read granularity; index 
files do not use this disk data cache |
 
-Use the profile counters and BE metrics in [Checking Cache 
Effectiveness](../catalogs/lance-catalog.mdx#checking-cache-effectiveness). An 
aggregate hit rate alone does not identify which index was evicted or which 
stage dominates latency. Change one setting at a time and keep a record of the 
workload, index version, BE placement, latency, throughput, recall, and peak 
memory for each comparison.
+Use the [Query Profile reference](lance-query-profile.md) to separate FE 
metadata/planning, BE index/scan work, and second-phase row-ID fetching. Use 
[Checking Cache 
Effectiveness](../catalogs/lance-catalog.mdx#checking-cache-effectiveness) for 
cache counters and BE-wide metrics. An aggregate hit rate alone does not 
identify which index was evicted or which stage dominates latency. Change one 
setting at a time and keep a record of the workload, index version, BE 
placement, latency, throu [...]
diff --git 
a/versioned_docs/version-4.x/lakehouse/best-practices/lance-hybrid-search.mdx 
b/versioned_docs/version-4.x/lakehouse/best-practices/lance-hybrid-search.mdx
index 26e07f480d9..8273b82fb27 100644
--- 
a/versioned_docs/version-4.x/lakehouse/best-practices/lance-hybrid-search.mdx
+++ 
b/versioned_docs/version-4.x/lakehouse/best-practices/lance-hybrid-search.mdx
@@ -181,13 +181,19 @@ Compare the same query set, dataset snapshot, index 
type/configuration, `top_k`,
 
 | Stage | Evidence | Interpretation |
 |---|---|---|
-| Planning and coverage | `EXPLAIN`: `lanceSearchIndexSegments`, 
`lanceSearchUnindexedFragments`; profile scanner counts | Confirm split count, 
fallback work, and whether the plan can use the intended layout. |
-| Prefilter | `LancePrefilterInputRows`, `LancePrefilterRowIds`, 
`LancePrefilterLoadTime`, `LancePrefilterBuildTime` | Load includes building 
the filter; do not add these timers. Large row-ID sets can dominate even 
without remote I/O. |
-| Scalar segment path | `LanceScalarIndexSegmentsRequested`, 
`LanceScalarIndexSegmentsSearched`, `LanceScalarIndexCandidateRows`, where 
populated | These counters describe the instrumented scalar-segment path, not 
necessarily every scalar lookup inside ANN/FTS. Zero is not proof that no 
scalar filtering happened. |
-| Index loading and search | `LanceIndexPartitionCacheMissLoads`, 
`LanceExecutionIOBytesRead`, `LanceIndexComparisons`; detailed index timers 
where available | Separate cache reloads from warm search and 
candidate-processing work. Zero I/O counters do not imply zero CPU work. |
-| Output fetch | Materialization operator and row-ID fetch timings, where 
present | Attribute output-column reads separately from candidate search. |
-| End-to-end latency | Slowest scanner, dependency waits, FE wait/fetch/write, 
and client wall time | Do not sum overlapping operators or all parallel scanner 
times into query latency. |
-
-Profile detail depends on the Doris build and bundled Lance instrumentation. 
Missing counters are not measured zeros. `FileScannerV2` includes scanner 
open/read/close work; its read interval can include Prefilter loading, index 
I/O, runtime waits, ANN search, refinement, and conversion. Nested or parallel 
counters are not an additive breakdown. If the exposed metrics cannot explain 
the interval, collect a CPU/I/O trace or use a build with the necessary 
detailed instrumentation before att [...]
+| FE metadata and planning | `Execution Summary` → `Lance Metadata Metrics`: 
`MetadataReadTime`, `IndexMetadataReadTime`, `SplitPlanningTime`, and 
corresponding `Calls` | Separate Catalog metadata access and split planning 
from BE search. Total metadata time contains its substeps. |
+| Planning and coverage | `EXPLAIN`: `lanceSearchIndexSegments`, 
`lanceSearchIndexFragments`, `lanceSearchUnindexedFragments`; 
`LanceSearchPlan`: `LancePlannedIndexSegmentCount`, 
`LancePlannedIndexedFragmentCount`, `LancePlannedFlatSearchFragmentCount` | 
These describe planned/assigned search work, not completed search. Flat Search 
counts apply to vector queries, not FTS. |
+| Reader setup and batch reads | `LanceTiming`: `LanceDatasetOpenTime`, 
`LanceScannerConfigureTime`, `LanceScannerNextTime`, 
`LanceArrowToDorisBlockTime` | Distinguish opening/configuration, Lance reads, 
and Doris conversion. Batch-read time includes internal search, I/O, decoding, 
and waits. |
+| Row-ID Prefilter | `LanceScan`: `RowIdPrefilterLoads`, 
`RowIdPrefilterInputRows`, `RowIdPrefilterInputBatches`, `RowIdPrefilterIds`, 
`RowIdPrefilterLoadTime`, `RowIdPrefilterInputTime`, `RowIdPrefilterBuildTime` 
| Input waiting/reading and mask construction are parts of total load time. 
These describe the row-ID loader, not every scalar predicate or final candidate 
set. |
+| Scalar segment path | `LanceScalarIndex`: 
`LanceScalarIndexSegmentsRequested`, `LanceScalarIndexSegmentsSearched`, 
`LanceScalarIndexSegmentFallbacks`, `LanceScalarIndexCandidateRows`, 
`LanceScalarIndexCandidateEvaluationTime`, `LanceScalarIndexSegmentSearchTime` 
| Candidate evaluation contains segment search. Candidate counts precede 
Fragment restriction/full filtering; repeated tasks can count candidates again, 
and unavailable cardinality can leave zero. |
+| Index reuse and I/O | `LanceIndex`: `LanceIndexCacheHits`, 
`LanceIndexCacheMisses`, `LanceIndexObjectLoads`, `LanceIndexComponentsLoaded`, 
`LanceIndexComparisons`; `LanceIO`: `LanceIOReadBytes`, `LanceIOReadOps`, 
`LanceIOReadRequests` | Separate object/component loading, cache lookups, and 
search work. Load counts are not miss counts; execution I/O is not a complete 
remote-traffic total. |
+| Vector partition selection and search | `LanceIVFPartitionsConsidered`, 
`LanceIVFPartitionSelectionTime`, `LanceIndexPartitionsSearched`, 
`LanceVectorIndexDeltasSearched`, `LanceIndexPartitionLoadTime`, 
`LanceIndexSearchTime`, `LanceIndexDistanceTopKTime` | Distinguish partition 
selection from actual search. Distance/Top-K time includes filtering and heap 
work, and overlaps search time. FTS also reports partitions searched. |
+| Waiting and concurrency | `LanceIndexPrefilterWaitTime`, 
`LanceIndexCpuQueueWaitTime`, `LanceScanTaskWaitTime` | Separate index 
Prefilter waiting, CPU task-queue waiting, and FilteredRead task waiting. None 
is a complete I/O-wait or Doris scheduling total. |
+| Output fetch | Row ID Fetch/Materialization information: 
`LanceRowIdFetchCalls`, `LanceRowIdFetchRows`, `LanceRowIdFetchTotalTime`, 
`LanceRowIdTakeReadTime`, `LanceArrowToDorisBlockTime`, and data-cache byte 
counters | Fetch totals include read/conversion substeps and use a separate 
statistics path. Do not add the same exported values again as independent work. 
|
+| End-to-end latency | Slowest Scanner, dependency waits, FE wait/fetch/write, 
and client wall time | Do not sum overlapping operators or all parallel Scanner 
times into query latency. |
+
+Use the [Lance Query Profile reference](lance-query-profile.md) for metric 
definitions and scope, and [Checking Cache 
Effectiveness](../catalogs/lance-catalog.mdx#checking-cache-effectiveness) for 
Dataset data-cache bytes and BE-wide Session metrics. Query-level index cache 
counters are not differences of Session totals.
+
+Profile detail depends on the running FE/BE and bundled Lance instrumentation. 
Scanner metrics are pre-registered; a zero can mean the native path did not 
report a metric. Execution callbacks also require completed streams, so failed, 
cancelled, or early-terminated scans can have incomplete counts. Missing or 
zero values alone do not prove that an index or filter was unused. 
`LanceScannerNextTime` overlaps internal search and waiting timers; a high 
value does not establish a storage bott [...]
 
 For an unfiltered vector query, a reader with the segment-scope optimization 
can avoid enumerating every row ID when the selected index segment is wholly 
inside the scan's fragment scope. Actual scalar predicates still need 
evaluation; deletion and visibility handling can also remain. Alignment reduces 
avoidable work but does not promise a zero-cost Prefilter for filtered 
retrieval.
diff --git 
a/versioned_docs/version-4.x/lakehouse/best-practices/lance-query-profile.md 
b/versioned_docs/version-4.x/lakehouse/best-practices/lance-query-profile.md
new file mode 100644
index 00000000000..936dd7574d6
--- /dev/null
+++ b/versioned_docs/version-4.x/lakehouse/best-practices/lance-query-profile.md
@@ -0,0 +1,158 @@
+---
+{
+    "title": "Lance Query Profile Reference",
+    "sidebar_label": "Lance Query Profile",
+    "language": "en",
+    "description": "Interpret Apache Doris Lance query profiles: FE metadata 
and planning, BE index and scan metrics, cache statistics, timing boundaries, 
and second-phase row-ID fetching.",
+    "keywords": [
+        "Lance",
+        "Query Profile",
+        "performance analysis",
+        "vector search",
+        "index cache"
+    ]
+}
+---
+
+This reference explains Profile metrics for ordinary Lance scans, vector 
search, full-text search, and second-phase row-ID fetching. For Profile 
collection, viewing, and general operator analysis, see the [Query Profile 
Analysis Guide](../../query-acceleration/query-profile.md). Configure Lance 
access using [Lance Catalog](../catalogs/lance-catalog.mdx).
+
+:::note
+Lance Catalog is experimental and supported starting from Apache Doris 4.2. 
The metrics below depend on the running FE/BE and bundled Lance version.
+:::
+
+Enable query profiling before running a Lance query:
+
+```sql
+SET enable_profile = true;
+```
+
+The following names describe the current Lance instrumentation.
+
+## FE Metadata and Planning
+
+For Catalog queries, including ordinary scans, `COUNT`, vector search, and 
full-text search, inspect `Lance Metadata Metrics` under `Execution Summary`:
+
+| Timer | Meaning |
+|---|---|
+| `MetadataReadTime` | Total time for a Catalog metadata read, including table 
access resolution, Dataset access, and resource cleanup. |
+| `TableAccessResolveTime` | Resolve table access, including Namespace access, 
credentials, and storage options. |
+| `DatasetOpenTime` | Open the Dataset on the FE. Historical queries can 
require more than one open. |
+| `VersionResolveTime` | Resolve the requested historical snapshot where 
needed. |
+| `SchemaReadTime` | Read the Arrow schema. |
+| `FragmentMetadataReadTime` | Read Fragment metadata and construct row-count 
descriptors. |
+| `FieldIdsReadTime` | Read and map Lance field IDs. |
+| `IndexMetadataReadTime` | Discover logical indexes and read index segment 
metadata. |
+| `SplitPlanningTime` | Plan ordinary, metadata-count, vector, or full-text 
scan splits. |
+
+Each executed operation or step also has a corresponding `Calls` counter, such 
as `DatasetOpenCalls`. `MetadataReadFailures` and `SplitPlanningFailures` count 
failed operations, including their elapsed time; they are not counts of failed 
SQL statements. Unexecuted metadata steps do not create counters. This group 
accumulates Catalog work across tables and repeated reads within the SQL 
statement; standalone file TVFs and `SHOW INDEX` do not populate it.
+
+`MetadataReadTime` contains its metadata substeps. `SplitPlanningTime` is 
measured separately. The generic `External Table Get Table Meta Time`, 
`External Table Get File Scan Tasks Time`, and `External Table Meta Time` 
include the corresponding work, so do not add them again to the Lance detail 
timers or to the enclosing analysis/planning time. FE `DatasetOpenTime` and BE 
`LanceDatasetOpenTime` describe different processes.
+
+## BE Groups and Statistics Boundaries
+
+In the scan Profile, find `TableReader` → `LanceReader`. Its groups are labels 
rather than timers; their hierarchy does not make child times additive.
+
+| Group | Content |
+|---|---|
+| `LanceTiming` | Dataset opening, Scanner configuration and reads, Runtime 
Filter translation, Arrow conversion, and row-ID fetching. |
+| `LanceIO` | Instrumented execution-stream read operations, requests, and 
bytes. |
+| `LanceIndex` | Index object/component loading, cache lookups, comparisons, 
index opening, and partitions searched. |
+| `LanceVectorIndex` | IVF partition selection, vector index deltas, ANN 
stages, and vector distance computation. |
+| `LanceScalarIndex` | Scalar index evaluation, segment search, candidates, 
fallbacks, and result serialization. |
+| `LanceExecutionPlan` | Lance execution-plan sorting, merging, and Take work. 
|
+| `LanceScan` | Fragment/range/row scans, scan-task waiting, and row-ID 
Prefilter construction. |
+| `LanceSearchPlan` | Search segment/Fragment counts assigned to the reader. |
+| `LanceDataCache` | Data-file cache and source-storage request bytes for the 
Dataset handle. |
+
+Doris timers update around their measured calls. Lance execution counters are 
accumulated from statistics callbacks after streams reach EOF. Failure, 
cancellation, or early termination can leave execution statistics incomplete. 
Scanner metrics are pre-registered, including optional native metrics: a zero 
value can mean that the native path did not report the metric. A missing or 
zero metric alone does not establish that an index, filter, or I/O path was 
unused. Metadata-only `COUNT` and  [...]
+
+Times accumulate across calls and parallel tasks, and can exceed SQL wall 
time. Read the slowest Scanner together with scheduling, dependency waits, FE 
result handling, and client latency. Do not sum all Scanners or nested timers 
to reconstruct query latency.
+
+## Reader Timing
+
+| Timer | Meaning |
+|---|---|
+| `LanceDatasetOpenTime` | Open the Dataset through the BE's shared Session, 
including necessary metadata access. Reusing the reader's already-open Dataset 
does not add another open. |
+| `LanceScannerConfigureTime` | Configure the Scanner, projection, filters, 
callback, and split/search options. Work deferred until reading is measured 
later. |
+| `LanceRuntimeFilterSqlTranslationTime` | Translate/combine Doris Runtime 
Filters into Lance SQL, including translation-cache lookup. This is not time 
spent executing the filter. |
+| `LanceScannerNextTime` | Cumulative batch-read calls, including initial 
preparation, index computation, I/O, decoding, and waiting. Excludes the 
subsequent Arrow-to-Doris conversion. |
+| `LanceArrowToDorisBlockTime` | Convert returned Arrow batches into Doris 
Blocks, for both scanning and row-ID fetching. |
+
+`LanceScannerNextTime` overlaps the internal index, scan, and execution-plan 
timers below. A large value does not by itself identify storage as the 
bottleneck.
+
+## I/O, Index Loading, and Cache Lookups
+
+| Counter | Meaning |
+|---|---|
+| `LanceIOReadOps` | Instrumented read-operation count, not operations per 
second or an HTTP request count. |
+| `LanceIOReadRequests` | Instrumented storage-read request count. Range 
merging/splitting can make it differ from `LanceIOReadOps`. |
+| `LanceIOReadBytes` | Read bytes reported by the execution plan, including 
instrumented data/index paths. Cache-served reads can be included; this is not 
measured remote traffic or decoded memory size. |
+| `LanceIndexObjectLoads` | Top-level index objects loaded. This is not a 
segment count or a count of their internal page loads. |
+| `LanceIndexComponentsLoaded` | Internal index components loaded, such as 
pages, partitions, or postings. This is not an index-cache miss counter; 
loading/merging and instrumentation can give different counts. |
+| `LanceIndexCacheHits`, `LanceIndexCacheMisses` | Cache lookups reported by 
instrumented index paths for this execution. They are distinct from BE-wide 
Session hit/miss totals. Some streaming paths do not retain loaded content, so 
persistent misses alone do not establish insufficient cache capacity. |
+| `LanceIndexComparisons` | Comparison/lookup work defined by each index 
implementation. This is not a candidate-row count or a uniform CPU-cost unit 
across index types. |
+
+These counters apply to the instrumented vector, scalar, and full-text index 
paths. An index object can remain cached while its pages or partitions need 
loading. Check cache usage, repeatable cold/warm workloads, and I/O together 
before increasing capacity. For the separate disk data cache and BE-wide 
metrics, see [Checking Cache 
Effectiveness](../catalogs/lance-catalog.mdx#checking-cache-effectiveness).
+
+## Row-ID Prefilter and Scalar Index Work
+
+Row-ID Prefilter metrics describe the loader that consumes row IDs and 
constructs an allowed-row mask. They do not measure every TVF `filter`, every 
scalar index lookup, or the final ANN/FTS result count.
+
+| Counter or timer | Meaning |
+|---|---|
+| `RowIdPrefilterLoads` | Physical row-ID loader executions. Repeated query 
nodes can perform repeated loads. |
+| `RowIdPrefilterInputRows`, `RowIdPrefilterInputBatches` | Non-null input row 
IDs and batches consumed by the loader. |
+| `RowIdPrefilterIds` | Allowed row IDs retained in the constructed mask, 
accumulated across loaders rather than deduplicated across the query. |
+| `RowIdPrefilterLoadTime` | Total loader time, including input polling and 
mask construction. |
+| `RowIdPrefilterInputTime`, `RowIdPrefilterBuildTime` | Input-stream 
waiting/reading and mask-building time. Both are included in 
`RowIdPrefilterLoadTime`; do not add the total to its parts. |
+| `LanceScalarIndexQueryTime` | Scalar index expression evaluation, 
potentially including several index searches and set operations. |
+| `LanceScalarIndexResultSerializationTime` | Serialize scalar index results 
for downstream Lance nodes; this is not network serialization or Arrow-to-Doris 
conversion. |
+| `LanceScalarIndexSegmentsRequested`, `LanceScalarIndexSegmentsSearched` | 
Requests for the explicit scalar-segment path and completed segment 
evaluations. These are execution counts, not distinct table segments. |
+| `LanceScalarIndexSegmentFallbacks` | Explicit scalar-segment acceleration 
falls back to a full-filter scan within the assigned Fragment scope. A searched 
segment can also fall back. |
+| `LanceScalarIndexCandidateRows` | Candidate-mask size when known, before the 
reader applies its Fragment scope and full predicate. It is not the SQL result 
count; zero can also reflect unavailable cardinality. |
+| `LanceScalarIndexCandidateEvaluationTime` | Prepare/evaluate/install 
scalar-segment candidates, including index opening/search and fallback 
preparation. Excludes the subsequent data scan. |
+| `LanceScalarIndexSegmentSearchTime` | Evaluate the selected segment's index 
expression, including its loading and set operations. Included in 
`LanceScalarIndexCandidateEvaluationTime`. |
+
+A segment can cover more Fragments than one task reads, and repeated tasks can 
count the same candidates again. Do not interpret `CandidateRows` as task-local 
matches. The regular scalar-expression path and explicit segment path have 
different timers; they need not report the same values. Large masks or repeated 
segment evaluation can consume CPU and memory even with a warm cache.
+
+## Vector and Execution-Plan Work
+
+| Counter or timer | Meaning |
+|---|---|
+| `LanceIVFPartitionsConsidered` | IVF partition population considered during 
selection, accumulated across the selected index deltas. This is not the number 
of probes executed. |
+| `LanceIVFPartitionSelectionTime` | Select IVF partitions for the query. 
Excludes the surrounding index open. |
+| `LanceIndexPartitionsSearched` | Partition searches actually reported by 
index execution. FTS also reports this metric; interpret it using 
`LanceSearchType`. It is not a query-wide distinct-partition count. |
+| `LanceVectorIndexDeltasSearched` | Vector index deltas submitted to the ANN 
partition path. This does not prove that every delta completed its search. |
+| `LanceIndexOpenTime` | Open an index handle, including cache lookup and 
metadata access. |
+| `LanceIndexPartitionLoadTime`, `LanceIndexPartitionPrepareTime` | Partition 
loading includes cache lookup, cache-fill waiting, and loading/decoding on a 
miss. Partition preparation includes loading and filter preparation; these 
timers overlap. |
+| `LanceIndexPrefilterWaitTime` | Wait for the index Prefilter to become 
ready. This is distinct from building a row-ID mask. |
+| `LanceIndexCpuQueueWaitTime` | Wait between submitting a partition search 
task and starting its CPU work. |
+| `LanceIndexSearchTime` | CPU search of a prepared partition, including query 
preparation and result construction. |
+| `LanceIndexQueryPrepareTime` | Construct the distance calculator and query 
lookup tables. |
+| `LanceIndexDistanceTopKTime` | Fused candidate filtering, distance 
evaluation, and Top-K heap updates. This is not a pure distance-computation or 
refinement timer. |
+| `LanceIndexResultMaterializeTime` | Convert a search-result heap into Arrow 
arrays/batches. This is not the Doris second-phase output fetch. |
+| `LanceANNPartitionExecTime`, `LanceANNSubIndexExecTime`, 
`LanceANNBatchExecTime` | Instrumented ANN execution-node compute times. These 
can overlap the detailed index timers. |
+| `LanceVectorDistanceComputeTime` | Compute time reported by the 
vector-distance execution node; it does not cover every indexed distance 
calculation. |
+| `LanceSortComputeTime`, `LanceSortMergeComputeTime`, `LanceTakeExecTime` | 
Lance execution-node sorting, merging, and Take compute times. These are not 
Doris TopN or the complete second-phase fetch. |
+
+Partition work runs concurrently and timers can nest or overlap. Do not add 
`LanceIndexSearchTime` to its query-preparation, distance/Top-K, and 
result-construction parts. Compare probe counts, CPU-queue waiting, Prefilter 
waiting, and I/O before changing `nprobes`, `ef`, or `refine_factor`; measure 
recall as well as latency.
+
+## Planned Work, Scanned Rows, and Output Fetch
+
+| Counter or timer | Meaning |
+|---|---|
+| `LancePlannedIndexSegmentCount` | Search index segments assigned to the 
reader, accumulated when splits are configured. Does not prove completed 
search. |
+| `LancePlannedIndexedFragmentCount` | Fragments assigned to indexed 
vector/full-text search splits. |
+| `LancePlannedFlatSearchFragmentCount` | Fragments assigned to vector Flat 
Search splits. FTS does not register this counter. |
+| `LanceFragmentsScanned`, `LanceRowOffsetRangesScanned`, `LanceRowsScanned` | 
Fragments, row-offset ranges, and rows reported by the FilteredRead path. Not 
all read paths populate them; they are not table-wide distinct counts or final 
SQL rows. |
+| `LanceScanTaskWaitTime` | FilteredRead consumer waiting for read tasks. This 
is not Doris Scanner scheduling time or a complete I/O-wait total. |
+| `LanceRowIdFetchCalls`, `LanceRowIdFetchRows` | Second-phase `take_rows` 
calls and rows fetched. |
+| `LanceRowIdTakeReadTime` | Create and consume the row-ID Take stream, 
including deferred reads; excludes Arrow-to-Doris conversion. |
+| `LanceRowIdFetchTotalTime` | Total non-empty row-ID fetch processing, 
including Dataset opening, Take reads, conversion, and result checks. It 
contains the preceding substeps, and excludes end-to-end RPC/Materialization 
overhead. |
+
+For search planning, compare `EXPLAIN` fields `lanceSearchIndexSegments`, 
`lanceSearchIndexFragments`, and `lanceSearchUnindexedFragments` with the 
`LanceSearchPlan` counters. For ordinary scalar-segment scans, use 
`lanceGroupingIndexSegments`, `lanceGroupingIndexedFragments`, and 
`lanceGroupingUnindexedFragments`; these are FE plan fields, not BE Profile 
counters. Fragment counts are accumulated by task and need not be deduplicated.
+
+Two-phase fetching uses a separate reader and does not register the Scanner 
execution-statistics callback. Its fetch timers, fetch counts, and 
`LanceDataCacheBytesReadFromCache`/`LanceDataCacheBytesReadFromRemote` are also 
reported in Row ID Fetch/Materialization Profile information. A missing 
`LanceIOReadBytes` there does not mean no I/O occurred. Keep scan and fetch 
scopes separate, and do not count the same exported fetch statistics twice.
+
+Use `LanceDatasetVersion` and `LanceDatasetUri` to identify the executed 
snapshot, and `LanceSearchType` to distinguish vector and full-text search. 
`LanceTopK`, `LanceOffset`, `LanceFtsCoverageMode`, `LanceFtsQueryType`, 
`LanceFtsMatchOperator`, `LanceFtsMaxFuzzyDistance`, `LanceFtsPhraseSlop`, 
`LancePushdownFormat`, and Runtime Filter ID entries describe configuration or 
pushdown state. They are information strings, not additive counters. 
`LanceTopK` and `LanceOffset` describe the per- [...]
+
diff --git a/versioned_docs/version-4.x/lakehouse/catalogs/lance-catalog.mdx 
b/versioned_docs/version-4.x/lakehouse/catalogs/lance-catalog.mdx
index a31f05fe3d2..2303fd5996e 100644
--- a/versioned_docs/version-4.x/lakehouse/catalogs/lance-catalog.mdx
+++ b/versioned_docs/version-4.x/lakehouse/catalogs/lance-catalog.mdx
@@ -721,6 +721,7 @@ FROM vector_search(
     "metric" = "l2",
     "nprobes" = "20",
     "refine_factor" = "10",
+    "prefilter" = "true",
     "filter" = "category = 'book'",
     "use_index" = "true"
 )
@@ -749,8 +750,9 @@ Do not use the unquoted form 
`lance_catalog.doris.analytics.items`; it parses as
 | `metric` | No | `l2` | Distance metric: `l2`, `cosine`, `dot`, or `hamming`. 
`dot_product` is an alias for `dot`. `uint8` vectors support only `hamming`; 
the other currently supported vector element types support `l2`, `cosine`, and 
`dot`. Set `metric` explicitly when querying a `cosine`, `dot`, or `hamming` 
index. Integer multi-vector columns and multi-vector `hamming` are unsupported. 
|
 | `distance_lower_bound` | No | Unbounded | Inclusive lower distance bound for 
single-vector search. Must be a finite `FLOAT`. |
 | `distance_upper_bound` | No | Unbounded | Exclusive upper distance bound for 
single-vector search. Must be a finite `FLOAT`. When both bounds are set, the 
lower bound must be smaller after conversion to `FLOAT`. |
-| `filter` | No | - | Lance SQL condition evaluated before vector candidates 
are generated; that is, a Prefilter. |
-| `nprobes` | No | Minimum `1`, with no maximum | Number of IVF index 
partitions to probe. It must be a positive integer. When unset, Lance starts 
with one partition and can probe additional partitions when a Prefilter leaves 
too few candidates. Setting it explicitly to `N` fixes both the minimum and 
maximum number of probes to `N`. |
+| `filter` | No | - | Lance SQL condition evaluated by Lance. Its execution 
timing is controlled by `prefilter`. |
+| `prefilter` | No | `false` | Controls when the TVF `filter` runs. `true` 
filters before vector candidates are generated; `false` (the default) filters 
after candidate generation, so the result can contain fewer than `top_k` rows. 
This parameter does not affect an outer Doris `WHERE`. |
+| `nprobes` | No | Minimum `1`, with no maximum | Number of IVF index 
partitions to probe. It must be a positive integer. When unset, Lance starts 
with one partition and can probe additional partitions when `prefilter=true` 
leaves too few candidates. Setting it explicitly to `N` fixes both the minimum 
and maximum number of probes to `N`. |
 | `refine_factor` | No | Single-vector: disabled; multi-vector: `1` | 
Candidate refinement multiplier. It must be a positive integer. For 
single-vector search, when unset, Lance does not recompute distances from the 
original vectors, so `_distance` from a quantized index may be approximate. 
When set to `N`, Lance first retrieves `(top_k + offset) × N` candidates, 
recomputes their exact distances from the original vectors, and reorders them. 
**Refinement reads the original vector data for [...]
 | `ef` | No | `floor(1.5 × (top_k + offset))` | Candidate width retained 
during HNSW graph search. It must be a positive integer. If `refine_factor` is 
also set, the default is `floor(1.5 × (top_k + offset) × refine_factor)`. It 
has no effect on non-HNSW indexes. |
 | `use_index` | No | `true` | When `true`, Doris prefers a Lance vector index 
compatible with the vector column and distance metric, and automatically uses 
Flat Search if no usable index is available. When `false`, Doris disables 
vector indexes and performs Flat Search over the data. |
@@ -793,7 +795,7 @@ ORDER BY _distance;
 +---------+-----------+
 ```
 
-Removing the lower bound also returns row 1. Using only an upper bound of `0` 
returns no rows. `filter` continues to restrict candidates before vector 
search, and `offset` skips results after applying the distance range. The 
output schema is unchanged: table columns plus `_distance` of type `FLOAT`. 
`EXPLAIN` displays `lanceDistanceRange=[1.0, 4.0)`.
+Removing the lower bound also returns row 1. Using only an upper bound of `0` 
returns no rows. With `prefilter=true`, `filter` restricts candidates before 
vector search; with the default `prefilter=false`, it filters after candidate 
generation. `offset` skips results after applying the distance range. The 
output schema is unchanged: table columns plus `_distance` of type `FLOAT`. 
`EXPLAIN` displays `lanceDistanceRange=[1.0, 4.0)`.
 
 Distance bounds support `?` parameters in prepared statements. Each execution 
validates and uses its own bound values; NULL bounds are rejected. Omit the 
property to leave that side unbounded.
 
@@ -904,7 +906,7 @@ Expected result:
 | 1 | 0.0 |
 | 2 | 2.0 |
 
-Row 1 contains a perfect match for each query subvector. Row 2 matches the 
first query subvector with distance `0` and the second with squared L2 distance 
`2`. Empty and null outer lists do not rank. Adding `"offset" = "1"` and 
changing `"top_k" = "1"` returns only row 2. Adding `"filter" = "id > 1"` 
restricts candidate search to matching rows and also returns only row 2 for 
this dataset.
+Row 1 contains a perfect match for each query subvector. Row 2 matches the 
first query subvector with distance `0` and the second with squared L2 distance 
`2`. Empty and null outer lists do not rank. Adding `"offset" = "1"` and 
changing `"top_k" = "1"` returns only row 2. Adding `"filter" = "id > 1"` and 
setting `"prefilter" = "true"` restricts candidate search to matching rows and 
also returns only row 2 for this dataset.
 
 #### Row-Level Scoring
 
@@ -955,7 +957,7 @@ The integrated Lance version supports multi-vector indexes 
with the **cosine** m
 
 With indexed search, candidate selection is approximate. Multi-vector 
candidates are **always refined against the original vectors**, including when 
`refine_factor` is omitted or set to `1`, so indexed and unindexed rows use the 
same row-level score. Increasing `refine_factor` expands the candidate pool, 
with additional vector reads and computation; it does not guarantee exhaustive 
recall. `nprobes` controls IVF probing and `ef` applies to HNSW indexes. Tune 
these only after measuring re [...]
 
-For exhaustive scoring of the selected rows, use `"use_index" = "false"`. 
Prefer the TVF `filter` to restrict candidates before search; an outer SQL 
`WHERE` can discard candidates without refilling a split's results. The 
filtering rules in the next section apply to both single-vector and 
multi-vector searches.
+For exhaustive scoring of the selected rows, use `"use_index" = "false"`. To 
restrict candidates before search, use the TVF `filter` with `prefilter=true`; 
the default `prefilter=false` applies the condition after candidate generation. 
An outer SQL `WHERE` is always evaluated by Doris against generated candidates 
and does not refill a split's results. The filtering rules in the next section 
apply to both single-vector and multi-vector searches.
 
 ### Prefilter and Post-Filter
 
@@ -968,6 +970,7 @@ FROM vector_search(
     "column" = "embedding",
     "query_vector" = "[0.1, 0.2, 0.3, 0.4]",
     "top_k" = "10",
+    "prefilter" = "true",
     "filter" = "category = 'book'"
 )
 WHERE user_id > 100
@@ -976,10 +979,11 @@ ORDER BY _distance ASC, user_id;
 
 | Filter type | Example condition | When it runs | Effect on results |
 |---|---|---|---|
-| Prefilter | TVF parameter `"filter" = "category = 'book'"` | Before Lance 
generates vector candidates | Searches for nearest neighbors only among rows 
where `category = 'book'`. |
-| Post-filter | Outer `WHERE user_id > 100` | After Lance generates candidates 
and before Doris applies the final TopN | Removes non-matching rows from the 
generated candidates. It does not replenish candidates, so the final result may 
contain fewer than `top_k` rows. |
+| TVF Prefilter | TVF parameters `"filter" = "category = 'book'"` and 
`"prefilter" = "true"` | Before Lance generates vector candidates | Searches 
for nearest neighbors only among rows where `category = 'book'`. |
+| TVF Post-filter | TVF parameter `"filter" = "category = 'book'"`, with 
`prefilter` omitted or set to `false` | After Lance generates candidates | 
Removes non-matching rows from the generated candidates. It does not replenish 
candidates, so the result may contain fewer than `top_k` rows. |
+| Doris Scan Post-filter | Outer `WHERE user_id > 100` | After Lance generates 
candidates and before Doris applies the final TopN | Removes non-matching rows 
from the generated candidates. It does not replenish candidates, so the final 
result may contain fewer than `top_k` rows. |
 
-If `user_id > 100` must also participate in candidate generation, include it 
in the TVF parameter, for example `"filter" = "category = 'book' AND user_id > 
100"`, instead of using an outer `WHERE`. Even if the optimizer moves the outer 
`WHERE` into the Doris Lance Scan, it remains a Post-filter and is not 
converted into a Lance Prefilter.
+If `user_id > 100` must also participate in candidate generation, include it 
in the TVF `filter` and set `prefilter=true`, for example `"filter" = "category 
= 'book' AND user_id > 100"`. With the default `prefilter=false`, that 
condition is applied after candidate generation. Even if the optimizer moves 
the outer `WHERE` into the Doris Lance Scan, it remains a Doris Scan 
Post-filter and is not converted into a Lance Prefilter.
 
 Lance reads and evaluates columns referenced only by `filter` internally. If 
such a column is not referenced by `SELECT` or another Doris expression, it 
does not have to be returned to Doris.
 
@@ -1059,15 +1063,16 @@ For workload-specific sizing formulas, configuration 
examples, shared-cache cont
 
 ### Checking Cache Effectiveness
 
-Inspect the following counters under `LanceReader` in the query Profile:
+Inspect index-cache counters under `LanceReader` → `LanceIndex`, and data-file 
cache counters under `LanceReader` → `LanceDataCache` in the completed query 
Profile:
 
 | Counter | Meaning |
 |---|---|
-| `LanceDataCacheBytesReadFromCache` | Logical bytes returned to the reader 
from cache hits through the data-cache path. |
-| `LanceDataCacheBytesReadFromRemote` | Logical bytes returned to the reader 
from source storage after data-cache misses. The source can also be a local 
file. |
-| `LanceIndexPartitionCacheMissLoads` | Index partitions loaded because of 
partition-cache misses, rather than the miss count for the entire index cache. |
+| `LanceIndexCacheHits`, `LanceIndexCacheMisses` | Cache lookups reported by 
instrumented index paths for this execution. These are separate from BE-wide 
Session metrics. |
+| `LanceIndexObjectLoads`, `LanceIndexComponentsLoaded` | Top-level index 
objects and internal components loaded. Neither is interchangeable with cache 
misses. |
+| `LanceDataCacheBytesReadFromCache` | Logical request bytes supplied by the 
data-file cache for this Dataset handle. |
+| `LanceDataCacheBytesReadFromRemote` | Logical request bytes supplied by 
source storage after misses or cache fallback. The source can also be a local 
file. |
 
-The two data-cache byte counters exclude extra bytes caused by block-aligned 
reads and I/O that bypasses the data cache, such as index and manifest reads. 
They are not complete remote-traffic counters. Both are `0` when the data cache 
is disabled, which does not imply that no source reads occurred. Statistics are 
collected when the Dataset closes, so inspect the completed query Profile. 
Second-phase fetches also reuse the cache, but these scan counters are not a 
query-wide total of all f [...]
+The two data-cache byte counters exclude block-read amplification and I/O that 
bypasses the data cache, such as index and manifest reads. They are not 
complete remote-traffic counters, and their sum need not equal 
`LanceIOReadBytes`. Both are `0` when the data cache is disabled, which does 
not imply that no source reads occurred. Doris records the Dataset handle's 
cumulative snapshot before closing it. Second-phase fetching has separate 
reader statistics, also exported to Row ID Fetch/Ma [...]
 
 The BE `/metrics` endpoint also exposes metrics prefixed with 
`doris_be_lance_session_index_cache_` and 
`doris_be_lance_session_metadata_cache_`. The suffixes `capacity_bytes`, 
`usage_bytes`, `entries`, `hits_total`, and `misses_total` represent configured 
capacity, current usage, entry count, cumulative hits, and cumulative misses. 
These metrics are registered after the shared Lance Session initializes and 
describe the BE-wide cache, rather than an individual query.
 
@@ -1110,7 +1115,7 @@ FROM vector_search(
 WHERE category = 'book';
 ```
 
-A Prefilter column referenced in the TVF `filter` is used internally by Lance. 
Its presence in the `filter` string alone does not make it a Phase-1 result 
column returned to Doris.
+Columns referenced in the TVF `filter` are used internally by Lance. Their 
presence in the `filter` string alone does not make them Phase-1 result columns 
returned to Doris; `prefilter` only changes when the condition is applied 
relative to candidate generation.
 
 ### Verifying the Plan
 
@@ -1152,6 +1157,7 @@ FROM full_text_search(
     "operator" = "and",
     "top_k" = "10",
     "offset" = "0",
+    "prefilter" = "true",
     "filter" = "category = 'storage'",
     "coverage_mode" = "strict"
 )
@@ -1159,7 +1165,7 @@ WHERE published = true
 ORDER BY _score DESC, document_id;
 ```
 
-This example uses Match AND, so a document must contain both analyzed terms, 
`lance` and `database`. The `filter` property is a Prefilter that Lance 
evaluates before generating FTS candidates. The outer `WHERE` is a Post-filter 
evaluated after candidate generation. A Post-filter does not replenish removed 
candidates, so the final result can contain fewer than `top_k` rows. If 
`published = true` must affect candidate generation, include it in `filter` 
instead.
+This example uses Match AND, so a document must contain both analyzed terms, 
`lance` and `database`. With `prefilter=true`, Lance evaluates `filter` before 
generating FTS candidates. When `prefilter` is omitted, its default is `false`, 
and Lance applies `filter` after candidate generation; the result can contain 
fewer than `top_k` rows. The outer `WHERE` is a Doris Post-filter and does not 
replenish removed candidates. If `published = true` must affect candidate 
generation, include it in [...]
 
 The following Phrase query permits at most one intervening token between 
adjacent query terms. For example, it can match `lance search engine`:
 
@@ -1190,7 +1196,8 @@ The returned relation contains every column from the 
source Lance table and a nu
 | `slop` | No | `0` | Phrase queries only. It must be an integer from `0` 
through `2147483647`. `0` requires an exact phrase; a positive value is the 
maximum number of intervening tokens permitted between adjacent query terms. 
Match queries cannot set this parameter. |
 | `top_k` | No | `10` | Number of results returned after skipping `offset`. It 
must be a positive integer. |
 | `offset` | No | `0` | Number of results skipped by relevance. It must be a 
non-negative integer, and `top_k + offset` must not exceed the maximum unsigned 
32-bit integer. |
-| `filter` | No | - | Lance SQL condition evaluated before full-text 
candidates are generated; that is, a Prefilter. |
+| `filter` | No | - | Lance SQL condition. Its execution timing is controlled 
by `prefilter`. |
+| `prefilter` | No | `false` | Controls when the TVF `filter` runs. `true` 
filters before full-text candidates are generated; `false` (the default) 
filters after candidate generation, so the result can contain fewer than 
`top_k` rows. This parameter does not affect an outer Doris `WHERE`. |
 | `coverage_mode` | No | `strict` | Behavior when the FTS index does not cover 
every Fragment in the current snapshot. Valid values are `strict` and 
`index_only`. |
 | `version`, `timestamp`, `tag`, `branch` | No | - | Search a historical 
version, the version at a time, a tag, or a branch instead of the latest 
version of `main`. See [Search a Historical Version or 
Branch](#search-a-historical-version-or-branch). |
 
@@ -1268,7 +1275,8 @@ Dataset snapshot selected by version / timestamp / tag / 
branch, or the latest v
   -> FE search Split planning
        -> Vector search: physical vector Index Segments + Flat Search for 
uncovered Fragments
        -> Full-text search: physical FTS Index Segments (coverage checked by 
coverage_mode)
-  -> Per Split: Lance Prefilter -> vector/full-text search -> at most K+n 
candidates
+  -> Per Split: vector/full-text search; the TVF `filter` runs before 
candidate generation when `prefilter=true`, and after candidate generation when 
`prefilter` is omitted or `false`
+       -> at most K+n candidates
   -> Doris Scan Post-filter
   -> Doris local TopN
   -> Exchange
@@ -1276,6 +1284,10 @@ Dataset snapshot selected by version / timestamp / tag / 
branch, or the latest v
   -> Optional lazy-materialization Fetch
 ```
 
+## Query Profile {#query-profile}
+
+For Profile collection and viewing, see the [Query Profile Analysis 
Guide](../../query-acceleration/query-profile.md). For Lance-specific groups, 
counters, timing boundaries, and second-phase fetch statistics, see the [Lance 
Query Profile Reference](../best-practices/lance-query-profile.md).
+
 ## Current Limitations and Recommendations
 
 - Lance Catalogs and Lance TVFs are read-only. `CREATE TABLE`, `INSERT`, 
`UPDATE`, `DELETE`, `TRUNCATE TABLE`, and writing data back to Lance are not 
supported.
@@ -1287,5 +1299,5 @@ Dataset snapshot selected by version / timestamp / tag / 
branch, or the latest v
 - Use `SHOW INDEX` on a Filesystem Catalog table to inspect its logical Lance 
indexes, for example to verify the index name, type, and indexed fields before 
vector or full-text search. `SHOW INDEX` is not supported for REST Catalogs.
 - For deterministic vector result ordering, explicitly use `ORDER BY _distance 
ASC` and add a unique tie-breaker.
 - For deterministic full-text result ordering, explicitly use `ORDER BY _score 
DESC` and add a unique tie-breaker.
-- Use the TVF `filter` parameter when filtering must occur before vector or 
full-text candidates are generated. An outer `WHERE` filters only the 
candidates already generated by each search Split and runs before Doris global 
TopN, so allow for a final result with fewer than `top_k` rows.
+- To filter before vector or full-text candidates are generated, set the TVF 
`filter` and `prefilter=true`; with the default `prefilter=false`, the TVF 
`filter` is applied after candidate generation. An outer `WHERE` is evaluated 
by Doris against candidates generated by each search Split before global TopN, 
so the final result may contain fewer than `top_k` rows.
 - Use `EXPLAIN` to inspect `lanceSearchFragments` and 
`lanceSearchIndexSegments`. The former is the number of visible Fragments in 
the pinned snapshot; the latter is the number of physical Index Segment splits 
selected by the FE. Vector search can also include fallback Flat Search 
Fragment splits; full-text search never falls back to Flat Search.
diff --git a/versioned_sidebars/version-4.x-sidebars.json 
b/versioned_sidebars/version-4.x-sidebars.json
index f06f2566a97..220ec2ad8a4 100644
--- a/versioned_sidebars/version-4.x-sidebars.json
+++ b/versioned_sidebars/version-4.x-sidebars.json
@@ -891,6 +891,7 @@
                 "lakehouse/best-practices/optimization",
                 "lakehouse/best-practices/doris-lance",
                 "lakehouse/best-practices/lance-hybrid-search",
+                "lakehouse/best-practices/lance-query-profile",
                 "lakehouse/best-practices/kerberos",
                 "lakehouse/best-practices/tpch",
                 "lakehouse/best-practices/tpcds"


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to