

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 向量搜尋概觀
<a name="vector-search-overview"></a>

向量搜尋是以建立、維護和使用索引為基礎。每個向量搜尋操作都會指定單一索引，其操作會受限於該索引，也就是說，一個索引上的操作不會受到任何其他索引上的操作影響。除了建立和銷毀索引的操作之外，可能隨時針對任何索引發出任意數量的操作，這表示在叢集層級，針對多個索引的多個操作可能會同時進行。

個別索引是存在於唯一命名空間中的具名物件，與其他 Valkey 和 Redis OSS 命名空間分開：索引鍵、函數等。每個索引在概念上類似於傳統資料庫資料表，因為它分為兩個維度：資料欄和資料列。資料表中的每一列對應至金鑰。索引中的每個資料欄對應至該索引鍵的成員或部分。在此文件中，術語索引鍵、資料列和記錄相同，可互換使用。同樣地，術語欄、欄位、路徑和成員基本上是相同的，也可以互換使用。

沒有要新增、刪除或修改索引資料的特殊命令。反之，修改索引中索引鍵的現有 **HASH**或 **JSON**命令也會自動更新索引。

**Topics**
+ [索引和 Valkey 和 Redis OSS 金鑰空間](#vector-search-indexes-keyspaces)
+ [索引欄位類型](#vector-search-index-field-types)
+ [向量索引演算法](#vector-search-index-algorithms)
+ [向量搜尋查詢表達式](#vector-search-query-expression)
+ [INFO 命令](#vector-search-ft.info)
+ [向量搜尋安全性](#vector-search-security)

## 索引和 Valkey 和 Redis OSS 金鑰空間
<a name="vector-search-indexes-keyspaces"></a>

在 Valkey 和 Redis OSS 金鑰空間的子集上建構和維護索引。多個索引可以選擇不相交或重疊的鍵空間子集，不受限制。每個索引的金鑰空間是由建立索引時提供的金鑰字首清單所定義。字首清單是選用的，如果省略，整個金鑰空間將是該索引的一部分。索引也會輸入，只涵蓋具有相符類型的索引鍵。目前僅支援 JSON 和 HASH 索引。HASH 索引只會為其字首清單所涵蓋的 HASH 索引鍵編製索引，類似地，JSON 索引只會為其字首清單所涵蓋的 JSON 索引鍵編製索引。索引的鍵空間字首清單中沒有指定類型的鍵會被忽略，不會影響搜尋操作。

當 HASH 或 JSON 命令修改索引鍵空間內索引已更新的索引鍵時。此程序涉及擷取每個索引的宣告欄位，並使用新值更新索引。更新程序是在背景執行緒中完成，這表示索引最終只會與其鍵空間內容一致。因此，在短時間內，在搜尋結果中不會顯示金鑰的插入或更新。在大量系統負載和/或大量資料變動期間，可見性延遲可能會變長。

建立索引是多步驟程序。第一步是執行定義索引的 [FT.CREATE](https://docs.aws.amazon.com/memorydb/latest/devguide/vector-search-commands-ft.create.html) 命令。成功執行建立會自動啟動第二個步驟 – 回填。回填程序會在背景執行緒中執行，並掃描金鑰空間，尋找新索引字首清單中的金鑰。找到的每個索引鍵都會新增至索引。最後掃描整個金鑰空間，完成索引建立程序。請注意，當回填程序正在執行時，允許索引索引鍵的變動，沒有任何限制，而且索引回填程序不會完成，直到所有索引鍵都正確編製索引為止。不允許在索引進行回填時嘗試查詢操作，並以錯誤終止。回填程序的完成可從該索引的 `FT.INFO`命令輸出 ('backfill\$1status') 決定。

## 索引欄位類型
<a name="vector-search-index-field-types"></a>

索引的每個欄位 （資料欄） 都有特定類型，會在建立索引時宣告，並在索引鍵中指定位置。對於 HASH 金鑰，位置是 HASH 中的欄位名稱。對於 JSON 金鑰，位置是 JSON 路徑描述。修改金鑰時，會擷取與宣告欄位相關聯的資料，並轉換為宣告類型，並存放在索引中。如果資料遺失或無法成功轉換為宣告的類型，則會從索引中省略該欄位。欄位有四種類型，如下所述：
+ **數字欄位**包含單一數字。對於 JSON 欄位，必須遵循 JSON 號碼的數值規則。對於 HASH， 欄位應包含以固定或浮點數標準格式寫入之數字的 ASCII 文字。無論金鑰中的表示法為何，此欄位都會轉換為 64 位元浮點數，以供索引內儲存。數字欄位可與範圍搜尋運算子搭配使用。由於基礎數字存放在具有精確度限制的浮點中，因此適用浮點數字比較的一般規則。
+ **標籤欄位**包含以單一 UTF-8 字串編碼的零個或多個標籤值。字串會使用分隔符號字元 （預設為逗號，但可以覆寫） 剖析為標籤值，並移除開頭和結尾的空格。任何數量的標籤值都可以包含在單一標籤欄位中。標籤欄位可用來透過區分大小寫或區分大小寫的比較，篩選標籤值相等性的查詢。
+ **文字欄位**包含不需要 UTF-8 合規的位元組 Blob。文字欄位可用來裝飾具有應用程式平均值的查詢結果。例如 URL 或文件的內容等。
+ **向量欄位**包含數字向量，也稱為內嵌。向量欄位支援使用指定演算法和距離指標進行固定大小向量的 K 近鄰搜尋 (KNN)。對於 HASH 索引， 欄位應包含以二進位格式編碼的整個向量 (*小端 IEEE 754*)。對於 JSON 金鑰，路徑應該參考填充數字的正確大小陣列。請注意，當 JSON 陣列用作向量欄位時，JSON 金鑰內陣列的內部表示會轉換為所選演算法所需的格式，從而減少記憶體消耗和精確度。使用 JSON 命令的後續讀取操作將產生降低的精確度值。

## 向量索引演算法
<a name="vector-search-index-algorithms"></a>

提供兩種向量索引演算法：
+ **平面** – 平面演算法是索引中每個向量的暴力力線性處理，在距離運算的精確度範圍內產生確切的答案。由於索引的線性處理，此演算法的執行時間對於大型索引可能非常高。
+ **HNSW (HNSW)** – HNSW 演算法是一種替代方法，可提供近似的正確答案，以換取大幅縮短的執行時間。演算法由三個參數 `M`、 `EF_CONSTRUCTION`和 控制`EF_RUNTIME`。前兩個參數是在索引建立時間指定，無法變更。`EF_RUNTIME` 參數具有在建立索引時指定的預設值，但之後可以在任何個別查詢操作上覆寫。這三個參數互動，在擷取和查詢操作期間平衡記憶體和 CPU 消耗，並控制精確 KNN 搜尋的近似品質 （稱為召回率）。

這兩種向量搜尋演算法 （平面和 HNSW) 都支援選用`INITIAL_CAP`參數。指定時，此參數會預先配置索引的記憶體，進而降低記憶體管理開銷並提高向量擷取速率。

像 HNSW 這樣的向量搜尋演算法可能無法有效地處理先前插入向量的刪除或覆寫。使用這些操作可能會導致索引記憶體消耗過多和/或召回品質降低。重新索引是還原最佳記憶體用量和/或召回的方法之一。

## 向量搜尋查詢表達式
<a name="vector-search-query-expression"></a>

[FT.SEARCH](https://docs.aws.amazon.com/memorydb/latest/devguide/vector-search-commands-ft.search.html) 和 [FT.AGGREGATE ](https://docs.aws.amazon.com/memorydb/latest/devguide/vector-search-commands-ft.aggregate.html)命令需要查詢表達式。此表達式是由一或多個運算子組成的單一字串參數。每個運算子在索引中使用一個欄位來識別索引中的索引鍵子集。可以使用布林值合併器和括號來組合多個運算子，以進一步增強或限制收集的金鑰集 （或結果集）。

### 萬用字元
<a name="vector-search-query-expression-wildcard"></a>

萬用字元運算子，星號 ('\$1')，符合索引中的所有索引鍵。

### 數值範圍
<a name="vector-search-query-expression-numeric-range"></a>

數值範圍運算子具有下列語法：

```
<range-search> ::= '@' <numeric-field-name> ':' '[' <bound> <bound> ']'
<bound>  ::= <number> | '(' <number>
<number> ::= <integer> | <fixed-point> | <floating-point> | 'Inf' | '-Inf' | '+Inf'
```

<numeric-field-name> 必須是類型 的宣告欄位`NUMERIC`。根據預設，邊界是包含的，但前置開放括號 【'('】 可用來使繫結排斥。 您可以使用 `+Inf`或 `-Inf` 做為其中一個邊界，將範圍搜尋轉換為單一關聯比較 (＜、<=`Inf`、＞、>=)。 無論指定的數值格式為何 （整數、固定點、浮點、無限），數字都會轉換為 64 位元浮點來執行比較，進而降低精確度。

**Example 範例**  

```
@numeric-field:[0 10]                      // 0   <= <value> <= 10
@numeric-field:[(0 10]                     // 0   <  <value> <= 10
@numeric-field:[0 (10]                     // 0   <= <value> <  10
@numeric-field:[(0 (10]                    // 0   <  <value> <  10
@numeric-field:[1.5 (Inf]                  // 1.5 <= value
```

### 標籤比較
<a name="vector-search-query-expression-tag-compare"></a>

標籤比較運算子具有下列語法：

```
<tag-search> ::= '@' <tag-field-name> ':' '{' <tag> [ '|' <tag> ]* '}'
```

如果運算子中的任何標籤符合記錄標籤欄位中的任何標籤，則記錄會包含在結果集中。設計的欄位`<tag-field-name>`必須是類型為 宣告之索引的欄位`TAG`。標籤比較的範例如下：

```
@tag-field:{ atag }
@tag-field: { tag1 | tag2 }
```

### 布林值組合
<a name="vector-search-query-expression-boolean-combinations"></a>

您可以使用布林邏輯： 和/或 來組合數值或標籤運算子的結果集。括號可用來將運算子分組和/或變更評估順序。布林值邏輯運算子的語法為：

```
<expression> ::= <phrase> | <phrase> '|' <expression> | '(' <expression> ')'
<phrase> ::= <term> | <term> <phrase>
<term> ::= <range-search> | <tag-search> | '*'
```

合併為片語的多個術語是「和」。與管道 ('\$1') 結合的多個片語為「或」。

### 向量搜尋
<a name="vector-search-query-expression-vector-search"></a>

向量索引支援兩種不同的搜尋方法：最近的相鄰和範圍。最近的鄰搜尋會尋找索引中最接近所提供 （參考） 向量之向量的數字 K，這稱為「K」最近鄰的 KNN。KNN 搜尋的語法為：

```
<vector-knn-search> ::= <expression> '=>[KNN' <k> '@' <vector-field-name> '$' <parameter-name> <modifiers> ']'
<modifiers> ::= [ 'EF_RUNTIME' <integer> ] [ 'AS' <distance-field-name>]
```

向量 KNN 搜尋只會套用至滿足 的向量`<expression>`，其可以是上述定義之運算子的任意組合：萬用字元、範圍搜尋、標籤搜尋和/或布林值組合。
+ `<k>` 是整數，指定要傳回的最近鄰向量數量。
+ `<vector-field-name>` 必須指定 類型的宣告欄位`VECTOR`。
+ `<parameter-name>` 欄位指定 `FT.SEARCH`或 `FT.AGGREGATE`命令`PARAM`資料表的其中一個項目。此參數是距離運算的參考向量值。向量的值會以*小端 IEEE 754* 二進位格式編碼為`PARAM`值 （與 HASH 向量欄位的編碼相同）
+ 對於 HNSW 類型的向量索引，選用子`EF_RUNTIME`句可用來覆寫建立索引時所建立`EF_RUNTIME`參數的預設值。
+ 選用 `<distance-field-name>`會提供結果集的欄位名稱，以包含參考向量和定位索引鍵之間的計算距離。

範圍搜尋會尋找與參考向量在指定距離 （半徑） 內的所有向量。範圍搜尋的語法為：

```
<vector-range-search> ::= ‘@’ <vector-field-name> ‘:’ ‘[’ ‘VECTOR_RANGE’ ( <radius> | ‘$’ <radius-parameter> )  $<reference-vector-parameter> ‘]’ [ ‘=’ ‘>’ ‘{’ <modifiers> ‘}’ ] 
<modifiers> ::= <modifier> | <modifiers>, <modifier> 
<modifer> ::= [ ‘$yield_distance_as’ ‘:’ <distance-field-name> ] [ ‘$epsilon’ ‘:’ <epsilon-value> ]
```

其中：
+ `<vector-field-name>`是要搜尋的向量欄位名稱。
+ `<radius> or $<radius-parameter>` 是搜尋的數值距離限制。
+ `$<reference-vector-parameter> ` 是包含參考向量的 參數名稱。向量的值會以小端 IEEE 754 二進位格式編碼為 PARAM 值 （與 HASH 向量欄位的編碼相同）
+ 選用 `<distance-field-name>`會提供結果集的欄位名稱，以包含參考向量和每個索引鍵之間的計算距離。
+ 選用 可`<epsilon-value> `控制搜尋操作的邊界，`<radius> * (1.0 + <epsilon-value>) `會周遊距離內的向量，尋找候選結果。預設值為 .01。

## INFO 命令
<a name="vector-search-ft.info"></a>

向量搜尋使用幾個額外的統計資料和計數器區段來增強 Valkey 和 Redis OSS [INFO](https://valkey.io/commands/info/) 命令。擷取區段的請求`SEARCH`將擷取下列所有區段：

### `search_memory` 區段
<a name="vector-search-ft.info-search-memory"></a>


| 名稱 | 描述 | 
| --- | --- | 
| search\$1used\$1memory\$1bytes | 所有搜尋資料結構中耗用的記憶體位元組數 | 
| search\$1used\$1memory\$1human | 上述的人類可讀版本 | 

### `search_index_stats` 區段
<a name="vector-search-ft.info-search_index_stats"></a>


| 名稱 | 描述 | 
| --- | --- | 
| search\$1number\$1of\$1indexes | 建立的索引數量 | 
| search\$1num\$1fulltext\$1indexes | 所有索引中的非向量欄位數量 | 
| search\$1num\$1vector\$1indexes | 所有索引中的向量欄位數目 | 
| search\$1num\$1hash\$1indexes | HASH 類型索引鍵上的索引數量 | 
| search\$1num\$1json\$1indexes | JSON 類型索引鍵上的索引數量 | 
| search\$1total\$1indexed\$1keys | 所有索引中的索引鍵總數 | 
| search\$1total\$1indexed\$1vectors | 所有索引中的向量總數 | 
| search\$1total\$1indexed\$1hash\$1keys | 所有索引中 HASH 類型的索引鍵總數 | 
| search\$1total\$1indexed\$1json\$1keys | 所有索引中 tytpe JSON 的索引鍵總數 | 
| search\$1total\$1index\$1size | 所有索引使用的位元組 | 
| search\$1total\$1fulltext\$1index\$1size | 非向量索引結構使用的位元組 | 
| search\$1total\$1vector\$1index\$1size | 向量索引結構使用的位元組 | 
| search\$1max\$1index\$1lag\$1ms | 上次擷取批次更新期間的擷取延遲 | 

### `search_ingestion` 區段
<a name="vector-search-ft.info-search_ingestion"></a>


| 名稱 | 描述 | 
| --- | --- | 
| search\$1background\$1indexing\$1status | 擷取的狀態。 NO\$1ACTIVITY表示閒置。其他值表示擷取過程中有索引鍵。 | 
| search\$1ingestion\$1paused | 除了重新啟動之外，這應該一律為「否」。 | 

### `search_backfill` 區段
<a name="vector-search-ft.info-search_backfill"></a>

**注意**  
只有在回填目前正在進行中時，才會顯示本節中記錄的一些欄位。


| 名稱 | 描述 | 
| --- | --- | 
| search\$1num\$1active\$1backfills | 目前回填活動的數量 | 
| search\$1backfills\$1paused | 除非記憶體不足，否則這應該一律為「否」。 | 
| search\$1current\$1backfill\$1progress\$1percentage | 目前回填的完成百分比 (0-100) | 

### `search_query` 區段
<a name="vector-search-ft.info-search_query"></a>


| 名稱 | 描述 | 
| --- | --- | 
| search\$1num\$1active\$1queries | 目前進行中 FT.SEARCH和 FT.AGGREGATE命令的數量 | 

## 向量搜尋安全性
<a name="vector-search-security"></a>

命令和資料存取的 [ACL （存取控制清單）](https://valkey.io/topics/acl/) 安全機制都會擴展，以控制搜尋設施。完全支援個別搜尋命令的 ACL 控制。提供了新的 ACL 類別 `@search`，並更新了許多現有類別 (`@fast`、`@write`、 `@read`等），以包含新的命令。搜尋命令不會修改金鑰資料，這表示會保留用於寫入存取的現有 ACL 機器。索引的存在不會修改 HASH 和 JSON 操作的存取規則；一般金鑰層級存取控制仍會套用至這些命令。

具有 索引的搜尋命令也會透過 ACL 控制其存取。存取檢查是在整個索引層級執行，而不是在每個金鑰層級。這表示只有在該使用者具有存取該索引之金鑰空間字首清單中所有可能金鑰的許可時，才會將索引的存取權授予使用者。換句話說，索引的實際內容不會控制存取。相反地，它是 索引的理論內容，由用於安全檢查的字首清單所定義。建立使用者對金鑰具有讀取和/或寫入存取權，但無法存取包含該金鑰的索引的情況很容易。請注意，建立或使用索引只需要對 金鑰空間的讀取存取權 – 不會考慮是否存在寫入存取權。

如需搭配 MemoryDB 使用 ACLs 的詳細資訊，請參閱[使用存取控制清單 (ACLs) 驗證使用者](https://docs.aws.amazon.com/memorydb/latest/devguide/clusters.acls.html)。