
# Lance表使用索引
#### 创建索引
可以对Lance表中的一列向量列构建索引，向量列需要被声明为fixed-size-list，请参见[创建Lance表](https://support.huaweicloud.com/devg-aidatalake/aidatalake_05_0044.html#aidatalake_05_0044__zh-cn_topic_0000002560961131_section4937183817479)。
向量索引类型可以是{ivfflat, ivfpq, ivfrq, ivfsq, hnsw, hnswpq, hnswsq}中的任意一种，建索引具体语法及约束，请参考[CREATE INDEX](https://support.huaweicloud.com/sqlref-aura-aidatalake/aidatalake_061_0231.html)。
支持分布式创建向量索引。产生的索引可以为一个全局索引，也可以是多个局部索引，其中局部子索引对应表的一个划分，对应被索引的数据互不重叠，可以通过设置fq_query_vdn控制表的分片数量。若建索引时参数merge_segment=1，则生成全局索引，否则生成多个子索引。使用多个子索引有利于分布式索引查询加速。
表1向量索引算法及其适用的场景 
| 索引类型    | 原理                                                            | 构建开销 | 压缩率 | 查询延迟/小top | 召回率 | 内存占用                                               | 使用场景                                                                                        | 调优参数                                                                                                                                                 |
|:---|:---|:---|:---|:---|:---|:---|:---|:---|
| ivfflat | 聚类分桶(partition)，存原始向量，查询时遍历分桶中心，仅扫描部分桶，索引扫描得出与查询向量精确距离        | 低    | 无   | 中         | 极高  | 高                                                  | 中小规模表，精度要求高，内存充足                                                                            | 建：nlists, sample_rate, max_iters 查：minimum_nprobes, maximum_nprobes, refine_factor                              |
| ivfpq   | 聚类分桶，存乘积量化码本及向量量化结果， 索引扫描基于量化的近似距离，可通过refine过程计算精确距离排序        | 中    | 高   | 较低        | 中   | 低                                                  | 亿级+，精度要求低，内存受限，大topK，混合标向量查询；需要平衡速度与精度，需要增大refine_factor以提升召回率，但较高的refine_factor(\>2)将会影响性能 | 建：nlists, sample_rate, max_iters, num_sub_vectors 查：minimum_nprobes, maximum_nprobes, refine_factor                |
| ivfrq   | 聚类分桶 存残差RabitQ (1-bit)，索引扫描得出近似距离，可refine过程精排                 | 较高   | 较高  | 中         | 高   | 中低                                                 | 亿级+，精度要求中等，内存受限，大topK，混合标向量查询；通过较低的refine_factor可得到高recall的结果                               | 建：nlists, sample_rate, max_iters, num_bits（目前仅支持1bit） 查：minimum_nprobes, maximum_nprobes, refine_factor         |
| ivfsq   | 聚类分桶，存标量量化 (8-bit)，索引扫描为近似距离，可通过refine精排                      | 中    | 中   | 中         | 高   | 中                                                  | 亿级+，精度要求高，内存较充足，大topK，混合标向量查询                                                               | 建：nlists, sample_rate, max_iters, num_bits 查：minimum_nprobes, maximum_nprobes, refine_factor                   |
| hnsw    | 聚类生成多层有向联通图，存原始向量，查询时通过导航图访问部分分桶中心，仅扫描部分桶，扫描为精确距离             | 高    | 无   | 低         | 极高  | 高 (\>ivfflat) | 亿级+，低延迟检索，小topK，高精度，混合查询时标量过滤器选择性较低；                                                        | 建：nlists, sample_rate, max_iters, m, ef 查：ef, refine_factor, minimum_nprobes, maximum_nprobes,                 |
| hnswpq  | 聚类生成多层有向联通图，存乘积量化码本及向量量化结果， 索引扫描基于量化的近似距离，可通过refine过程计算精确距离排序 | 极高   | 高   | 低         | 中   | 中                                                  | 亿级+，低延迟检索，小topK，低精度，混合查询时标量过滤器选择性较低；需要增大refine_factor以提升召回率                                 | 建：nlists, sample_rate, max_iters, m, ef, num_sub_vectors 查：ef, refine_factor, minimum_nprobes, maximum_nprobes, |
| hnswsq  | 聚类生成多层有向联通图，存标量量化 (8-bit)，索引扫描为近似距离，可通过refine精排               | 高    | 中   | 低         | 高   | 较高                                                 | 亿级+，低延迟检索，小topK，较高精度，混合查询时标量过滤器选择性较低；                                                       | 建：nlists, sample_rate, max_iters, m, ef, num_bits 查：ef, refine_factor, minimum_nprobes, maximum_nprobes,      |
   
**示例**：
为Lance表lance_tbl建立一个名为lance_index_01的索引，指定算法为ivfpq，索引距离函数为L2距离，索引的数据包含2类，每个向量可以被量化分解为4个子向量，将生成多个子索引。
```
CREATE INDEX IF NOT EXISTS lance_index_01 ON lance_tbl USING ivfpq (vector_column vector_l2_ops) WITH (nlists=2, num_subvectors=4, merge_segment=0);
```
表2标量索引算法及其适用的场景 
| 索引类型  | 原理                                                                      | 使用场景                     | 支持的数据类型                                                                                                                                                                                                                                                                                                                                                                         | 参数 |
|:---|:---|:---|:---|:---|
| btree | 按值排序分页，内存中存每页 min/max 构建查找树，查询时先通过 BTree 裁剪无关页面，再仅扫描少量候选页中的原始数据，返回精确结果。 | 范围查询、等值查询、IN 查询、大数据集精确过滤 | 整数：tinyint, smallint, int, integer, bigint, long 浮点：real, float, double precision, double 布尔：boolean 字符串：varchar(n), char(n), string, text 时间：date, timestamp 小数：decimal(p,s), numeric(p,s) | 无  |
   
**示例**：
为Lance表lance_tbl中column_name列建立一个名为lance_idx的索引，指定算法为btree。
```
CREATE INDEX IF NOT EXISTS lance_idx ON lance_tbl USING btree (column_name);
```
表3全文索引算法及其适用的场景 
| 索引类型     | 原理                                                  | 使用场景       | 支持的数据类型                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | 参数                                                                                                     |
|:---|:---|:---|:---|:---|
| inverted | 按照分词器对原始句子进行分词，查询时基于查询的单词或短语，根据倒排表找到对应的原始数据，返回精确结果。 | 单词匹配、短语匹配。 | - 文本：text  - 变长字符：varchar  - 定长字符：bpchar  - 文本数组：text\[\]  - 变长字符数组：varchar\[\]  - 定长字符数组：bpchar\[\]   | base_tokenizer、with_position、max_token_length，关于参数的详细说明，请参见[表5]。 |
   
![](https://support.huaweicloud.com/devg-aidatalake/public_sys-resources/note_3.0-zh-cn.png)
在Aura中Lance格式标量索引当前只支持btree类型，全文索引只支持inverted类型。
**示例**：
为Lance表lance_tbl中column_name列建立一个名为lance_fts的索引，指定算法为全文索引，指定分词器为ngram（支持中文），指定包含位置（用于短语查询），指定最大token长度是20（超过将被截断）。
```
CREATE INDEX IF NOT EXISTS lance_fts ON lance_tbl USING inverted (column_name) WITH (base_tokenizer = 'ngram', with_position = true, max_token_length = 20);
```
表4全文索引可用的分词器 
| 分词器值                    | 说明                                                      | 特性依赖     |
|:---|:---|:---|
| simple                  | 按空白符和标点分词（默认）                                           | 始终可用     |
| whitespace              | 仅按空白符分词                                                 | 始终可用     |
| raw                     | 不分词，整个文本作为单个 token                                      | 始终可用     |
| ngram                   | N-Gram 分词（重叠字符序列），需配合 min_ngram_length/max_ngram_length | 始终可用     |
| icu                     | ICU 基于词典的 Unicode 分词                                    | 始终可用     |
| lindera/\<model\>       | Lindera 日语形态分析（如 lindera/ipadic）                        | 需要手动下载词典 |
| jieba 或 jieba/\<model\> | Jieba 中文分词（jieba 等同于 jieba/default）                     | 需要手动下载词典 |
   
 表5参数说明 
| 参数名              | 类型     | 默认值    | 推荐值                                                                                                                                                                                                                                                                                                                                                                                                                                 | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
|:---|:---|:---|:---|:---|
| base_tokenizer   | String | simple | - 英文用 "simple"  - 中文用 "jieba/ngram"  - 日语用 "lindera/ipadic"  - 模糊前缀搜索用 "ngram"   | 基础分词器，决定文本如何被切分为 token。可选值： - simple（按空白和标点分词）  - whitespace（仅按空白分词）  - raw（不分词）  - ngram（N-Gram 重叠字符序列）  - icu（ICU Unicode 分词）  - lindera/\<model\>（日语形态分析）  - jieba（中文分词）   |
| with_position    | bool   | false  | - 需要短语查询时设为 true  - 仅做关键词检索时保持false                                                                                                                                                                                                | 是否在倒排索引中存储 token 位置信息。true 支持短语查询，但索引体积会显著增大（可达 10 倍+）。ngram 分词器不支持此参数                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| max_token_length | uint32 | 40     | - 一般场景保持默认 40  - 中文/日文等无空格分词的语言建议设为 None  - 需要contains_tokens加速时必须设为None                                                                                     | token文本长度上限，长度\>=该值的token会被过滤掉。设为None表示不限制。设为非None值会导致contains_tokens SQL查询无法走索引加速                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
   
#### 展示已有索引
您可以打印出当前数据库全部Lance表或某一Lance表上的全部索引，具体语法，请参考[SHOW INDEX](https://support.huaweicloud.com/sqlref-aura-aidatalake/aidatalake_061_0233.html)。
**示例**：
```
SHOW INDEX;
SHOW INDEX lance_tbl;
```
#### 删除已有索引
可以删除某一Lance表上的一个已建好的索引，语法参考[DROP INDEX](https://support.huaweicloud.com/sqlref-aura-aidatalake/aidatalake_061_0232.html)。
**示例**：
```
DROP INDEX lance_index_01 ON lance_tbl;
```
#### 重建或更新已有索引
![](https://support.huaweicloud.com/devg-aidatalake/public_sys-resources/caution_3.0-zh-cn.png)
更新Lance索引列的数据会导致部分索引片段或者整个索引失效，需要定期执行optimize来增量重建索引。
可以基于一个已有的索引重建索引，重建的索引将使用相同的索引名及索引参数，但索引的数据是该索引列的最新的全量数据。具体语法，请参考[ALTER INDEX](https://support.huaweicloud.com/sqlref-aura-aidatalake/aidatalake_061_0234.html)。
**示例**：
```
ALTER INDEX IF EXISTS lance_index_01 ON lance_tbl REBUILD;
```
可以基于一个已有的索引更新索引。当有新数据插入或删除时，已经建好的索引不会立即更新，从而不能根据索引查找到最新数据，会影响查询性能（但不会影响结果集）。
为使已有索引包含最新数据，可以使用索引优化功能避免全量数据重建索引。索引优化后，将可以根据索引找到最新的全量数据。
具体语法，请参考[ALTER INDEX](https://support.huaweicloud.com/sqlref-aura-aidatalake/aidatalake_061_0234.html)。
**示例**：
```
ALTER INDEX IF EXISTS lance_index_01 ON lance_tbl OPTIMIZE;
```
