# Lance Late Read调优说明
Late Read（延迟读）是Lance外表针对向量top-k查询的性能优化特性。该特性通过将数据扫描拆分为"早读阶段"和"延迟读"两个阶段，显著减少宽列（如图片、长文本、原始向量）的无效读取量，从而提升查询性能。
在普通计划下，**SELECT \<宽列\> FROM t ORDER BY vec \<-\> q LIMIT k**需要把全表所有候选行的全部投影列读出来，再排序取top-k。宽列（图片、bytea、长文本、原始向量）在排序前被读取，绝大部分随后被丢弃。
Late Read把扫描分为两步：
1. 早读阶段：只读_rowid、xc_node_id、_distance三个系统列，加上WHERE谓词列/JOIN key列，走IVF索引产出候选集，排序取top-k。
2. 延迟读阶段：把top-k的_rowid按xc_node_id路由回数据所在DN（RESTORE流），只对这k行调用Lance take_rows取回宽列。宽列的读取量从O(候选行数 × 宽列宽度) 降到O(k × 宽列宽度)。
#### Late Read执行策略
Late Read支持两种执行策略，您可以通过参数指定或由优化器自动选择。
- 一阶段（single_phase） 一次Late Read把向量列和其他宽列一起取回。
  图1一阶段Late Read计划示意图   
  ![](https://support.huaweicloud.com/devg-aidatalake/zh-cn_image_0000002729083009.png)
  **特点**：计划层次浅、只有一次RESTORE+一次take_rows，但宽列是为粗排候选集取的，其中会有一部分行在后续精排中被淘汰，这部分宽列IO是浪费的。
  

- 二阶段（two_phase） 把延迟读拆成两次，先只取向量列做精排定稿，再只为最终k行取宽列。
  图2二阶段Late Read计划示意图   
  ![](https://support.huaweicloud.com/devg-aidatalake/zh-cn_image_0000002699335148.png)
  **特点**：宽列严格只为最终k行读取，宽列IO最省，代价是多一轮RESTORE流和一次Python侧take_rows调用。只有当非向量宽列足够宽、足够多时才划算。
  
 
#### GUC参数说明
**late_read_strategy**
- **参数说明**：设置Lance DFS表top-k查询的Late Read策略。取值为列表，其中none/single_phase/two_phase/auto四个策略选项互斥，nested_late_read和join_late_read分别为独立开关。
- **取值范围** ：
  - none：关闭Late Read。走原始计划，所有投影列在扫描阶段一次读全。
  
  - auto：由优化器按代价与列宽自动在none、single_phase、two_phase之间选择。
  
  - single_phase：规则强制走一阶段，跳过收益检查。
  
  - two_phase：规则强制走二阶段，跳过收益检查。
  
  - nested_late_read：独立开关，允许Late Read在嵌套查询块（子查询、CTE）中生效。
    - 未设置时（默认）：子查询和CTE内部的查询不走Late Read。
    
    - 设置后：每个查询块独立判定Late Read，子查询和CTE内部的top-k查询可以走Late Read。
     
  
  - join_late_read：独立开关，允许Late Read跨INNER JOIN生效（仅支持hashjoin）。设置后，Late Read仍需同时满足以下全部条件方可生效：
    - 所有连接均为INNER JOIN（存在outer/semi/anti join则回退为普通计划）。
    
    - 查询中有且仅有一个Lance top-k驱动表，且查询中Lance表数量与之相等。
    
    - 驱动表存在等值连接条件。
    
    - 无聚集、GROUP BY、DISTINCT、集合操作。
     
   
- **默认值**：none。
 
**enable_topk_compensation**
- **参数说明**：设置是否开启Lance ANN扫描的top-k补偿读。开启后，Lance ANN扫描使用基于filter_ratio的k值计算和while-loop补偿机制，确保WHERE过滤后仍能返回LIMIT n行。
- **取值范围** ：
  - on：开启后，会启动while-loop补偿机制，确保最终输出的行数满足k值要求。
  
  - off：关闭时，当where过滤率比较大时，可能输出远小于k值的行数。
   
- **默认值**：off。
 
