含まれる列

ベクトル索引の含まれる列は、近傍パーティション・ベクトル索引内に非ベクトル列を組み込むことで、属性フィルタによる検索を高速化します。

住宅価格データを分析する典型的な例について考えてみます。価格が200万ドル未満または特定の郵便番号(あるいはその両方)の条件指定を満たす上位10軒の住宅のみを選び出します。または、より細かい条件指定およびフィルタ属性に一致する上位の住宅のみを取得する必要があります。含まれる列は、価格や郵便番号などのフィルタ可能な属性をベクトル索引に直接組み込むことで、これを可能にします。この統合により、索引はベクトル類似度と属性フィルタの両方に基づいて結果を評価および返すことができ、実表を相互参照するための追加のステップを必要としません。

従来のデータベース・フィルタとAIを利用したベクトル検索のギャップを埋めることで、含まれる列ではより迅速で効率的な結果を得ることができます。この相乗効果により、特に高度な類似度計算とともにきめ細かいフィルタリングが必要なユースケースで、検索のパフォーマンスが向上します。

構文と指定

今年販売されたすべての製品の売上データを含む実表を作成します:
create table houses(id number, zip_code number, price number, 
description clob, data_vector vector);
その後、次のように含まれる列にpriceを使用してIVF索引を作成できます。
create vector index vidx_ivf on houses(data_vector) include (price) 
organization neighbor partitions with target accuracy 95 
distance EUCLIDEAN parameters(type IVF, neighbor partitions 2);

前述の構文では、DATA_VECTOR列に対してorganizationNEIGHBOR PARTITIONSであるベクトル索引VIDX_IVFが作成され、PRICE列が含まれる列です。INCLUDEキーワードを使用すると、ユーザーはIVF索引で含める属性を指定できます。

ノート:

含まれる列は、パーティション・ローカル索引では機能しません。
IVF索引には、重心表(IVF_FLAT_CENTROIDS)と重心パーティション表(IVF_FLAT_CENTROID_PARTITIONS)の2つの補助表があることを思い出してください。次のコード・ブロックは、含まれる列がない重心パーティション表を示しています:
  Name					   Null?    Type
 ----------------------------------------- -------- ----------------------------
 BASE_TABLE_ROWID			   NOT NULL ROWID
 CENTROID_ID				   NOT NULL NUMBER
 DATA_VECTOR					    VECTOR(384, FLOAT32, DENSE)
--------------------------------------------------------------------------------
含まれる列のリストは、IVF索引のIVF_FLAT_CENTROID_PARTITIONS表に拡張されます。BASE_TABLE_ROWID列は、暗黙的な含まれる列とみなすことができます。次の表に、含まれる列が最後の行として拡張されたIVF_FLAT_CENTROID_PARTITIONS表を示します。この場合、priceです。
 Name					   Null?    Type
 ----------------------------------------- -------- ----------------------------
 BASE_TABLE_ROWID			   NOT NULL ROWID
 CENTROID_ID				   NOT NULL NUMBER
 DATA_VECTOR					    VECTOR(384, FLOAT32, DENSE)
 PRICE						    NUMBER
--------------------------------------------------------------------------------

実表に対するDML操作では、含まれる列も保守されます。含まれる列の実表の行を更新すると、IVF索引の重心パーティションもすべて更新されます。

ノート:

INCLUDEの制限事項:

INCLUDEリストには次のものを含めることができます:

  • 最大31列に制限されます。Oracle索引では、32個のキー列がサポートされます。
  • 次のデータ型のみがサポートされます: NUMBERCHARVARCHAR2DATETIMESTAMPRAWJSON、およびBLOBCLOBなどの参照ベースのLOB型。
  • NLS型およびLONG型はサポートされていません。

含まれる列を使用する利点

  1. 含まれる列がある場合とない場合のIVFでのフィルタリングなし:

    指定されたベクトルに最も近い2つの住宅をフェッチするためのフィルタリングを使用しない問合せを考えた場合、結果として得られる問合せは、複数の結合を含む実行計画になります。

    select /*+ VECTOR_INDEX_TRANSFORM(t) */ price from houses t order by 
    VECTOR_DISTANCE(data_vector, :query_vector) fetch first 2 rows only;
    

    ノート:

    query_vectorには、実際の入力ベクトルが含まれています。「FLOAT32ベクトル・ジェネレータを使用したSQLクイック・スタート」で説明されている手順を使用して、query_vectorを生成できます。
    複数の結合が次の実行計画に表示されています:
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 466477707
    
    ------------------------------------------------------------------------------------------------------
    | Id  | Operation			| Name							     |
    ------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT		|							     |	     
    |   1 |  VIEW				|							     |	   	     
    |   2 |   NESTED LOOPS			|							     |	   
    |   3 |    VIEW 			| VW_IVPSR_11E7D7DE					     |	   
    |*  4 |     COUNT STOPKEY		|							     |	     
    |   5 |      VIEW			| VW_IVPSJ_578B79F1					     |	   
    |*  6 |       SORT ORDER BY STOPKEY	|							     |	   
    |   7 |        NESTED LOOPS		|							     |	   
    |   8 | 	VIEW			| VW_IVCR_B5B87E67					     |	   
    |*  9 | 	 COUNT STOPKEY		|							     |	     
    |  10 | 	  VIEW			| VW_IVCN_9A1D2119					     |	   
    |* 11 | 	   SORT ORDER BY STOPKEY|							     |	 
    |  12 | 	    TABLE ACCESS FULL	| VECTOR$VIDX_IVF$74478_74488_0$IVF_FLAT_CENTROIDS	     |	   
    |  13 | 	PARTITION LIST ITERATOR |							     |	   
    |* 14 | 	 TABLE ACCESS FULL	| VECTOR$VIDX_IVF$74478_74488_0$IVF_FLAT_CENTROID_PARTITIONS |	   
    |  15 |    TABLE ACCESS BY USER ROWID	| HOUSES						     |	   
    ------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       4 - filter(ROWNUM<=2)
       6 - filter(ROWNUM<=2)
       9 - filter(ROWNUM<=1)
      11 - filter(ROWNUM<=1)
      14 - filter("VW_IVCR_B5B87E67"."CENTROID_ID"="VTIX_CNPART"."CENTROID_ID")
    

    この実行計画では、IVF重心が重心パーティション表と結合され、重心表からフェッチされた最も近い近傍パーティションの重心をスキャンすることがわかります。この操作は予期されたものです。ただし、実表(HOUSES)との結合を実行して属性フィルタも適用しています。列が重心パーティション表に含まれている場合、実表に対するこの2番目の結合を回避できます。

    次の実行計画には、含まれる列を使用して作成された近傍パーティション・ベクトル索引(IVF)を使用した場合の同じ操作が示されています。
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 504484986
    
    -------------------------------------------------------------------------------------------------------
    | Id  | Operation		       | Name							      |
    -------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT	       |							      |  
    |   1 |  VIEW			       |							      |   
    |   2 |   VIEW			       | VW_IVPSR_11E7D7DE					      |  
    |*  3 |    COUNT STOPKEY	       |							      |       
    |   4 |     VIEW		       | VW_IVPSJ_578B79F1					      |     
    |*  5 |      SORT ORDER BY STOPKEY     |							      |   
    |   6 |       NESTED LOOPS	       |							      |   
    |   7 |        VIEW		       | VW_IVCR_B5B87E67					      |   
    |*  8 | 	COUNT STOPKEY	       |							      |   
    |   9 | 	 VIEW		       | VW_IVCN_9A1D2119					      |    
    |* 10 | 	  SORT ORDER BY STOPKEY|							      |    
    |  11 | 	   TABLE ACCESS FULL   | VECTOR$VIDX_IVF_1$74483_74508_0$IVF_FLAT_CENTROIDS	      |    
    |  12 |        PARTITION LIST ITERATOR |							      |     
    |* 13 | 	TABLE ACCESS FULL      | VECTOR$VIDX_IVF_1$74483_74508_0$IVF_FLAT_CENTROID_PARTITIONS |    
    -------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       3 - filter(ROWNUM<=2)
       5 - filter(ROWNUM<=2)
       8 - filter(ROWNUM<=1)
      10 - filter(ROWNUM<=1)
      13 - filter("VW_IVCR_B5B87E67"."CENTROID_ID"="VTIX_CNPART"."CENTROID_ID")
    

    前述の実行計画からわかるように、ベクトル索引に含まれる列を追加すると、実表の事前フィルタ評価が不要になります。この問合せは、近傍パーティション・ベクトル索引の重心パーティション表をスキャンすることで解決できます。

  2. 含まれる列を使用したIVFでのフィルタリング:

    近傍グラフ・ベクトル索引でより一般的に使用される計画の1つは、事前フィルタ計画です。この場合、実表の内容をフィルタリングして、無関係な行を排除します。ただし、フィルタ属性を使用しない問合せの評価は、操作に複数の結合が含まれるため、非常にコストがかかる場合があります。次の問合せでは、含まれる列を使用しない近傍パーティション・ベクトル索引を使用しています。

    SELECT /*+VECTOR_INDEX_TRANSFORM(houses, vidx_ivf) */ price FROM houses 
    WHERE price = 1400000 ORDER BY vector_distance(data_vector, :query_vector) 
    FETCH APPROX FIRST 4 ROWS ONLY;
    

    ノート:

    query_vectorには、実際の入力ベクトルが含まれています。「FLOAT32ベクトル・ジェネレータを使用したSQLクイック・スタート」で説明されている手順を使用して、query_vectorを生成できます。

    実行計画には、複数の結合と、実表HOUSESとの必須の結合が示されています。

    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 3359903466
    
    -------------------------------------------------------------------------------------------------------------
    | Id  | Operation			       | Name							    | 
    -------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT		       |							    |	
    |*  1 |  COUNT STOPKEY			       |							    |	
    |   2 |   VIEW				       |							    |	
    |*  3 |    SORT ORDER BY STOPKEY	       |							    |	
    |   4 |     NESTED LOOPS		       |							    |	
    |   5 |      MERGE JOIN CARTESIAN	       |							    |	
    |*  6 |       TABLE ACCESS FULL 	       | HOUSES 						    |	
    |   7 |       BUFFER SORT		       |							    |	
    |   8 |        VIEW			       | VW_IVCR_2D77159E					    |	 
    |*  9 | 	COUNT STOPKEY		       |							    |	 
    |  10 | 	 VIEW			       | VW_IVCN_9A1D2119					    |	 
    |* 11 | 	  SORT ORDER BY STOPKEY        |							    |	  
    |  12 | 	   TABLE ACCESS FULL	       | VECTOR$VIDX_IVF$74478_74488_0$IVF_FLAT_CENTROIDS	    |	  
    |* 13 |      TABLE ACCESS BY GLOBAL INDEX ROWID| VECTOR$VIDX_IVF$74478_74488_0$IVF_FLAT_CENTROID_PARTITIONS |	 
    |* 14 |       INDEX UNIQUE SCAN 	       | SYS_C008791						    |	  
    -------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - filter(ROWNUM<=4)
       3 - filter(ROWNUM<=4)
       6 - filter("HOUSES"."PRICE"=1400000)
       9 - filter(ROWNUM<=3)
      11 - filter(ROWNUM<=3)
      13 - filter("VW_IVCR_2D77159E"."CENTROID_ID"="VTIX_CNPART"."CENTROID_ID")
      14 - access("HOUSES".ROWID="VTIX_CNPART"."BASE_TABLE_ROWID")
    
    一方、priceincluded列として使用して作成したIVF索引に対して同じフィルタ内問合せを使用した場合、実行計画に表示される結合が少なくなり、実表との結合は回避されます。これを次の計画に示します:
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 4183240211
    
    -------------------------------------------------------------------------------------------------------
    | Id  | Operation		       | Name							      |
    -------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT	       |							      |
    |*  1 |  COUNT STOPKEY		       |							      | 
    |   2 |   VIEW			       |							      |  
    |*  3 |    SORT ORDER BY STOPKEY       |							      | 
    |*  4 |     HASH JOIN		       |							      |
    |   5 |      PART JOIN FILTER CREATE   | :BF0000						      | 
    |   6 |       VIEW		       | VW_IVCR_2D77159E					      | 
    |*  7 |        COUNT STOPKEY	       |							      | 
    |   8 | 	VIEW		       | VW_IVCN_9A1D2119					      | 
    |*  9 | 	 SORT ORDER BY STOPKEY |							      |  
    |  10 | 	  TABLE ACCESS FULL    | VECTOR$VIDX_IVF_1$74483_74508_0$IVF_FLAT_CENTROIDS	      |  
    |  11 |      PARTITION LIST JOIN-FILTER|							      |  
    |* 12 |       TABLE ACCESS FULL        | VECTOR$VIDX_IVF_1$74483_74508_0$IVF_FLAT_CENTROID_PARTITIONS |  
    -------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - filter(ROWNUM<=4)
       3 - filter(ROWNUM<=4)
       4 - access("VW_IVCR_2D77159E"."CENTROID_ID"="VTIX_CNPART"."CENTROID_ID")
       7 - filter(ROWNUM<=3)
       9 - filter(ROWNUM<=3)
      12 - filter("VTIX_CNPART"."PRICE"=1400000)