13.1 ユビキタス検索とユビキタス検索索引について

ユビキタス検索では、スキーマ全体における複数オブジェクトに対する全文および範囲ベースの問合せを実行できます。ユビキタス検索索引(または単にDBMS_SEARCH索引)を使用して、ユビキタス検索を実行できます。

ユビキタス検索索引は、表、ビューまたはJSON二面性ビューに対する全文検索を実行できるようにする、一連のプリファレンスと設定が事前定義されているJSON SEARCH INDEXタイプです。これらの索引の作成、管理および問合せには、DBMS_SEARCH PL/SQLパッケージを使用します。

DBMS_SEARCH索引は、SELECT権限を持つスキーマの表またはビューに対して作成できます。データ・ソース(つまり、表およびビュー)をこの索引に追加できます(ビューをマテリアライズする必要はない)。指定したソース内のすべての列が索引付けされ、全文または範囲ベースの検索に使用できます。

ユビキタス検索インデックスを選択する理由

この索引付け手法を使用すると、複数のオブジェクトにまたがる索引の作成、データ・ソースの追加または削除、同じ索引を使用した単一のデータ・ソース内または複数のソース間の全文または範囲ベースの検索を実行できます。これにより、以前(Oracle Database 23aiより前)は複数の個別の索引を作成し、MULTI_COLUMN_DATASTOREまたはUSER_DATASTOREプロシージャとマテリアライズド・ビューを使用して様々なデータ・ソースを手動で結合する必要があった索引付けタスクが簡略化されます。以前は、索引がDML操作と同期されたままであることを確認するために、トリガーなどの追加のメソッドも必要でした。

DBMS_SEARCH APIの簡略化されたセットを使用すると、次のように、データベース全体でユビキタス検索を実行できます:

  • 索引の作成:

    DBMS_SEARCH.CREATE_INDEX APIでは、DBMS_SEARCH索引を作成できます。

    デフォルトでは、この索引は、ワイルドカード検索を可能にするBASIC_WORDLISTや、全文および範囲検索の問合せを可能にするSEARCH_ONなど、キー索引プリファレンスを使用して作成されます。これらの索引は事前定義された間隔でバックグラウンドで非同期的にメンテナンスされるため、このような索引に対してSYNC_INDEX操作とOPTIMIZE_INDEX操作を明示的に実行する必要はありません。

  • データ・ソースの管理:

    データ・ソースとして表またはビューを索引に追加することで、どの表またはビューを索引付けするか定義できます。

    DBMS_SEARCH.ADD_SOURCE APIでは、1つ以上のデータ・ソース(表、ビュー、二面性ビューなど)を様々なスキーマからこの索引に自動的に追加できます。

    DBMS_SEARCH.REMOVE_SOURCE APIでは、ソースおよびそれに関連するすべてのデータを索引から削除できます。

  • 結合された索引付きデータの表示:

    DBMS_SEARCH.GET_DOCUMENT APIでは、索引付けされた仮想ドキュメントを表示できます。このドキュメントでは、すべてのデータ・ソースの各行について、メタデータ値が索引付け済として表示されます。

  • 複数のオブジェクトの問合せ:

    DBMS_SEARCH.FIND APIでは、指定したフィルタ条件に基づいてすべてのドキュメントのヒットリストを取得できます。

この索引は、事前定義された間隔でバックグラウンド・ジョブを作成し、DML変更を同期させ、すべてのデータ・ソースでAUTO_DAILYモードを使用して索引を最適化します。この索引に対してSYNC_INDEXおよびOPTIMIZE_INDEX操作を明示的に実行する必要はありません。

ユビキタス検索索引作成の概要

DBMS_SEARCH索引を作成するには、索引名を指定してから、様々なデータ・ソースを追加します。次の図にこれを示します。

  1. 最初のコマンド(DBMS_SEARCH.CREATE_INDEXプロシージャ)では、[schema].index_nameとして索引表が作成されます。[schema].index_nameという名前のユビキタス検索索引も、索引表のDATA列に作成されます。なお、索引表名は索引名と一致します。

    ここでは、スキーマ所有者名(SCOTT)は、索引名(MYINDEX)とともにSCOTT.MYINDEXとして指定されます。

  2. 2番目のコマンド(DBMS_SEARCH.ADD_SOURCEプロシージャ)では、様々なスキーマから1つ以上のデータ・ソース(表、ビュー、二面性ビューなど)を追加します。

    ここでは、このプロシージャは、ScottのスキーマにあるPRODUCTS表およびCUSTOMERS表のすべての列の内容をMYINDEX表に結合します。

MYINDEX表には次の列があります:

  • DATA (JSONデータ型):

    これは空の列であり、DBMS_SEARCH索引を問い合せるためのプレースホルダです。データ・ソースをDATA列に追加します。次に、CONTAINS()JSON_TEXTCONTAINS()およびJSON_EXISTS演算子を使用して、このDATA列に対してPL/SQL問合せを実行できます。

    DATA列では、この索引にデータ・ソースとして追加される表またはビューの索引付き行ごとに、次の形式のJSON表現が作成されます:

    {"OWNER":
      {
       "TABLE_NAME":{"COLUMN1_NAME":"COLUMN1_VALUE",…}
      }
    }

    DATA列に実際のデータは格納されないことに注意してください。かわりに、データは元の実表に存在します。この索引は、データ・ソース表を参照して、索引付けされた仮想JSONドキュメントをその場で作成します。データがフェッチおよび索引付けされた後、この列は事実上空になり、重複が回避されます。

  • METADATA (JSONデータ型):

    METADATA列は、DBMS_SEARCH索引で、索引付けされた表またはビューの各行を一意に識別するために役立ちます。この索引にデータ・ソースを追加した後、METADATA列には、データ・ソースの索引付き行ごとに、次の形式のJSON表現が格納されていることを確認できます:

    {
     "OWNER"  : "Table_Owner or View_Owner",
     "SOURCE" : "Table_Name or View_Name", 
     "KEY"    : "{PrimaryKey_COLUMN_i" : PrimaryKey_VALUE_i}
    }

    OWNERは、この索引にデータ・ソースとして追加された表またはビューの所有者を指定します。

    SOURCEは、データ・ソースの表名またはビュー名を指定します。

    KEYは、データ・ソース表のすべての主キー列で構成されます。表に主キーがない場合には、かわりにROWIDが使用されます。ただし、主キーを定義することをお薦めします。

    図に示すように、METADATA列には、索引付き行ごとに次の形式の対応するJSONエントリが格納されます:

    PRODUCTS表の場合:

    {"OWNER":"SCOTT","SOURCE":"PRODUCTS","KEY":{"ID":1}}
    {"OWNER":"SCOTT","SOURCE":"PRODUCTS","KEY":{"ID":2}}

    CUSTOMERS表の場合:

    {"OWNER":"SCOTT","SOURCE":"CUSTOMERS","KEY":{"ID":5}}
    {"OWNER":"SCOTT","SOURCE":"CUSTOMERS","KEY":{"ID":9}}

    ノート:

    DBMS_SEARCH索引では、サポートされているすべてのSQLデータ型(Object Type列を含む)がJSONオブジェクトとして格納されます(XMLTYPEおよびLONGデータ型を除く)。したがって、表またはビューは、XMLTYPEまたはLONGデータ型の列がある場合、データ・ソースとして追加できません。

  • OWNER、SOURCE、KEY (VARCHAR2データ型):

    METADATA列の各JSONキー(つまり、OWNERSOURCEおよびKEY)は、MYINDEX表内の別々の仮想列でもあります。

    MYINDEX表はOWNERおよびSOURCEによってパーティション化されていることに注意してください。特定のデータ・ソースを問い合せるときは、OWNERおよびSOURCEの仮想列にWHERE句条件を追加すると、パーティション・プルーニングを使用して問合せ検索をそのソースの特定のパーティションに限定できます。

    ノート:

    DBMS_SEARCH索引に追加するすべてのデータ・ソース(表、ビュー、ビュー定義の各表など)には、少なくとも1つのPrimary Key列が含まれている必要があります。外部キーがあるビュー・ソースに含まれている各表には、その表で定義されている関連する主キーを参照するForeign Key制約も必要です。ソース表に主キーがない場合には、かわりにROWIDが使用されます。

索引付きデータの問合せ

前述したとおり、DBMS_SEARCH.GET_DOCUMENTプロシージャを使用して、仮想ドキュメントを問い合せることにより、元の実表から抽出されたすべての内容を表示できます。このドキュメントには、データ・ソースとして索引に追加される表またはビューの索引付き行ごとにJSON表現が含まれています。

DBMS_SEARCH.GET_DOCUMENTの構文は次のとおりです:

SELECT DBMS_SEARCH.GET_DOCUMENT('[schema].index_name', METADATA) 
 from [schema].index_name;

たとえば、前述したPRODUCTSおよびCUSTOMERSソース表のシナリオを使用すると、次の文は、結合されたメタデータ値がMYINDEX索引で索引付けされた仮想ドキュメントを返します:

SELECT DBMS_SEARCH.GET_DOCUMENT('SCOTT.MYINDEX',METADATA) 
  from SCOTT.MYINDEX;

DBMS_SEARCH.GET_DOCUMENT('SCOTT.MYINDEX', METADATA)
-----------------------------------------------------------------
{
  "SCOTT" :
  {
    "PRODUCTS" :
    {
      "ID"          : 1,
      "PRICE"       : 10,
      "DESCRIPTION" : "simple widget"
    }
  }
}
{
  "SCOTT" :
  {
    "PRODUCTS" :
    {
      "ID"          : 2,
      "PRICE"       : 2000,
      "DESCRIPTION" : "shiny thing"
    }
  }
}
{
  "SCOTT" :
  {
    "CUSTOMERS" :
    {
      "ID"         : 5,
      "FIRSTNAME"  : "Robert",
      "LASTNAME"   : "Smith"
    }
  }
}
{
  "SCOTT" :
  {
    "CUSTOMERS" :
    {
      "ID"         : 9,
      "FIRSTNAME"  : "John",
      "LASTNAME"   : "Doe"
    }
  }
}

CONTAINSJSON_TEXTCONTAINSおよびJSON_EXISTS演算子を使用して、索引に対して問合せを実行できるようになりました。

DBMS_SEARCHディクショナリ・ビュー

次のディクショナリ・ビューを使用して、ユビキタス検索索引を調べることができます:

  • USER_DBMS_SEARCH_INDEXES: ユーザーのスキーマに作成された索引に関する情報を問い合せます。

  • ALL_DBMS_SEARCH_INDEXES: 各索引所有者に対応する、既存のすべての索引に関する情報を問い合せます。

  • USER_DBMS_SEARCH_INDEX_SOURCES: ユーザーのスキーマに作成された、索引に追加されたデータ・ソースに関する情報を問い合せます。

  • ALL_DBMS_SEARCH_INDEX_SOURCES: 各索引所有者に対応する、索引に追加された既存のすべてのデータ・ソースに関する情報を問い合せます。