1.8 結果表を使用した問合せ実行の高速化

結果表は、RDFグラフまたはRDFグラフ・コレクションに対して実行されるSPARQL問合せの一般的なパターンの結果を格納する補助表です。

ノート:

結果表は、以前のブック・バージョン(Oracle Databaseリリース23aiより前)でSubject-Property-Matrix (SPM)表としてコールされました。詳細は、「用語とサブプログラムの変更」を参照してください。

一般的なパターン問合せには、スターパターン、チェーン・パターンおよび単一トリプル・パターン問合せが含まれます。

結果表によるパフォーマンスの向上は、次を使用することで実現されます。

  • これらの表で事前マテリアライズド結合を使用すると問合せ処理時の結合が減少します
  • 別々の表内の個々のプロパティについてトリプルのコンパクト表現を使用するとアクセスがより迅速になります
  • これらの表から取得した、より正確なRDFデータ統計を使用すると、問合せ実行計画が改善されます

次のセクションでは、結果表について詳しく説明します。

1.8.1 結果表のタイプ

RDFグラフまたはRDFグラフ・コレクションには、3つのタイプの結果表を定義できます。

様々な結果表を次に示します。

  • スターパターン表: これらの表には、次のようなスターパターン問合せの結果が保持されます(各プロパティは単一値である必要があります)。

    ?x :fname ?fnm . ?x miname ?m . ?x :lname ?lnm .

  • トリプルパターン表: これらの表には、次のような単一のトリプルパターン問合せの結果が保持されます。

    ?x :hasHobby ?y .

    これはRDFトリプルと同じですが、特定のプロパティの場合です。

  • チェーンパターン表: これらの表には、次のようなチェーンパターン問合せの結果が保持されます。

    ?child :hasParent ?parent . ?parent :hasBrother ?uncle .

    チェーンは、すべてのリンクが存在する場合にのみ格納されます。

ノート:

スターパターン表、トリプルパターン表、チェーンパターン表は、以前のブック・バージョン(Oracle Databaseリリース23aiより前)でそれぞれ単一値プロパティ(SVP)表、複数値プロパティ(MVP)表、プロパティ・チェーン(PCN)表と呼ばれていました。詳細は、「用語とサブプログラムの変更」を参照してください。

次のサンプル・データを含むRDFグラフについて考えてみます。

:john :fname "John" ; :lname "Brown" ; :height 72 ; :email "john@email-example.com", "johnnyB@email-example.com" .
:mary :fname "Mary" ; :lname "Smith" ; :height 68 ; :email "Mary.Smith@email-example.com" .
:bob :fname "Robert" ; :lname "Brown" ; :height 70 ; :fatherOf :john, :mary ; :email "bobBrown@email-example.com" .
:alice :fname "Alice" ; :lname "Brown" ; :height 68 ; :motherOf :john, :mary .
:henry :fatherOf :bob .
:kathy :motherOf :bob .

なお、わかりやすくなるように、rdftermごとに実際の数値識別子(RDF_VALUE$表にある)のかわりにId(rdfterm)が使用されます。例1-107には、追加データを含む完成した例が含まれています。

1.8.1.1 スターパターン表

スターパターン表内の各行には、RDFグラフ内の1つのリソースについて1つ以上の単一値RDFプロパティの値が保持されます。

すべて理想的に進んだ場合には、n個のプロパティについて定義されているスターパターン表を問合せ処理中に使用して、RDF_LINK$表のn方向結合を単純な表参照に置き換えることができます。

プロパティpがRDFグラフでの単一値となるのは、名前付きグラフであるかどうかを問わず、グラフ内の各リソースにあるpの値が最大でも1つの場合です。サンプルRDFデータセット(「結果表のタイプ」を参照)では、プロパティ:first_name:last_nameおよび:heightは単一値ですが、プロパティ:emailは複数値です。

単一値プロパティのみを使用する{ ?s :first_name ?fname ; :last_name ?lname ; :height ?height }などの問合せパターンの実行を高速化するには、SEM_APIS.BUILD_RESULT_TABサブプログラムのコールで文字列':first_name :last_name :height'key_stringパラメータの値として使用することで、前述の3つの単一値プロパティを含めてRDFグラフにスターパターン表を作成します。

表1-19に、前述のサンプル・データに対応するスターパターン表の構造と内容を示します。また、次のことに注意してください:

  • この表は、実際の列セットのサブセットのみを示しています。厳密に述べると、対応するRDF文の名前付きグラフ・コンポーネントの格納に使用されるG<Id(property)>のような名前の列は示していません。
  • この表では、列の値を、格納される実際の数値識別子ではなく、Id(rdfterm)として示しています。

表1-19 スターパターンの表構造の例

START_NODE_ID P<Id(:first_name)> P<Id(:last_name)> P<Id(:height)>
Id(:john) ... Id(“John”) ... Id(“Brown”) ... Id(72)
Id(:mary) ... Id(“Mary”) ... Id(“Smith”) ... Id(68)
Id(:bob) ... Id(“Robert”) ... Id(“Brown”) ... Id(70)
Id(:alice) ... Id(“Alice”) ... Id(“Brown”) ... Id(68)

このスターパターン表を使用できることで、スターパターン表内の行にアクセスするだけで前述の問合せパターンを処理でき、そうでなければ必要な、RDF_LINK$表の3方向自己結合を回避できます。

単一値である逆プロパティを含めることもできます。サンプルRDFデータ(「結果表のタイプ」を参照)では、プロパティ:fatherOfは単一値ではありませんが、^:fatherOf (:hasFatherプロパティと直観的に同等)として示されるその逆バージョンは、実際には単一値です。{ ?s :fname ?fname; :lname ?lname; :height ?height; ^:fatherOf ?father }などの問合せパターンの実行を高速化するには、':fname :lname :height ^:fatherOf'key_string値として使用することで、前述のスターパターン表の拡張バージョンを作成します。

表1-20に、逆プロパティを含む、この拡張バージョンのスターパターン表の構造と内容を示します。列名の先頭文字としてPではなくRを使用することで(R<Id(:fatherOf)>)、これが逆プロパティであることを示します。前述のように、このスターパターン表を使用できることで、RDF_LINK$表の(4方向)自己結合を回避できます。

表1-20 逆プロパティを含む拡張スターパターン表

START_NODE_ID P<Id(:first_name)> P<Id(:last_name)> P<Id(:height)> R<Id(:fatherOf)>
Id(:john) ... Id(“John”) ... Id(“Brown”) ... Id(72) ... :bob
Id(:mary) ... Id(“Mary”) ... Id(“Smith”) ... Id(68) ... :bob
Id(:bob) ... Id(“Robert”) ... Id(“Brown”) ... Id(70) ... :henry

例1-98 スターパターン表の作成

次のコードでは、M1という名前のRDFグラフに拡張スターパターン表が作成されます。

BEGIN
  SEM_APIS.BUILD_RESULT_TAB(
     query_pattern_type => SEM_APIS.SPM_TYPE_SVP
   , result_tab_name    => 'FLHF'
   , rdf_graph_name     => 'M1'
   , key_string         => ' :fname :lname :height ^:fatherOf '
   , prefixes           => ' PREFIX : <http://www.example.com#> ' 
   , network_owner      => 'RDFUSER'
   , network_name       => 'NET1'
  );
END;
/

スターパターン表の名前、構造およびデフォルト索引は、次のように記述できます:

  • スターパターン表の名前は、次のテンプレートに基づいて作成されます:

    <NETWORK_NAME>#RDF_XT$SVP_<MODEL_NAME>+__<SPM_NAME>

  • NUMBER列であるSTART_NODE_IDには、スターパターン表内のプロパティのリストにおける最初のプロパティについて、一致するトリプルの、主語ID、または逆プロパティの場合は目的語IDが格納されます。
  • スターパターン表でカバーされているプロパティごとに、字句値の数値識別子をトリプルに格納するために次の列が作成されます:
    • 指定されたグラフIDを格納するためのNUMBER列(G<Id(property)>)。
    • 目的語IDを格納するためのNUMBERP<Id(property)>、または逆プロパティの場合は主語IDを格納するためのR<Id(property)>
    • (オプション)内部使用のためのその他の列。
  • START_NODE_ID列はスターパターン表の主キーとして定義され、テンプレート<NETWORK_NAME>#RDF_XX$SVP_<MODEL_NAME>_UQ__<SPM_NAME>を使用して名付けられた一意の索引が、SVP表の作成時にこの列に作成されます。

1.8.1.2 トリプルパターン表

指定されたプロパティ用に作成されたトリプルパターン表内の各行には、そのプロパティの値が保持されます。

トリプルパターン表には、別個の表内の指定されたプロパティの値がコンパクトな形式で格納されます。これにより、アクセスが迅速になり、統計が改善されます。スターパターン表と異なり、トリプルパターン表に含まれる(単一)プロパティは必須ではありませんが、単一値である可能性があります。

名前付きグラフであるかどうかを問わず、2つ以上のトリプルがあり、それらは(s p o1)および(s p o2)で、o1o2と等しくない場合、RDFグラフではプロパティpは複数値です。つまり、sには、プロパティpに対して複数の異なる目的語値があります。

サンプルRDFデータセット(「結果表のタイプ」を参照)では、プロパティ:email:fatherOfおよび:motherOfが複数値です。

表1-21に、前述のサンプル・データでの:motherOfプロパティについて、トリプル・パターン表の構造と内容を示します。ここで示す2つの列には、変数?momおよび?cの字句値の数値識別子が、それぞれパターン{ ?mom :motherOf ?c }で格納されます。トリプルパターン表には、一致するRDF文がクワッドの場合に名前付きグラフの数値識別子を格納するために、ここに示されていない別の列G<id<:motherOf>)が含まれています。

表1-21 トリプルパターンの表構造の例

START_NODE_ID ... P<Id(:motherOf)>
Id(:alice)   Id(:john)
Id(:alice)   Id(:mary)
Id(:kathy)   Id(:bob)

例1-99 トリプルパターン表の作成

M1という名前のRDFグラフで前述のトリプル・パターン表を作成するには、次のSQLコマンドを使用します。

BEGIN
  SEM_APIS.BUILD_RESULT_TAB(
     query_pattern_type => SEM_APIS.SPM_TYPE_MVP
   , result_tab_name    => null /* must be NULL (the name is auto-generated based on id(property) */
   , rdf_graph_name     => 'M1'
   , key_string         => ' :motherOf ' /* must have exactly one property */
   , prefixes           => ' PREFIX : <http://www.example.com#> ' 
   , network_owner      => 'RDFUSER'
   , network_name       => 'NET1'
  );
END;
/

トリプルパターン表の名前、構造およびデフォルト索引は、次のように記述できます:

  • トリプルパターン表の命名規則は、次のテンプレートに基づいて作成されます:

    <NETWORK_NAME>#RDF_XT$MVP_<MODEL_NAME>+__P<id(property)>

  • NUMBER列であるSTART_NODE_IDには、ターゲット・プロパティを述語として使用する、一致するトリプルの主語IDが格納されます。
  • トリプル・パターン表でカバーされているプロパティについて、字句値の数値識別子をトリプルに格納するために次の列が作成されます:
    • 指定されたグラフIDを格納するためのNUMBERG<Id(property)>
    • 目的語IDを格納するためのNUMBERP<Id(property)>
    • 内部使用のための、オプションのその他の列
  • 一意でない索引が、<NETWORK_NAME>#RDF_XX$MVP_<MODEL_NAME>_P<id(property)>という命名規則を使用してSTART_NODE_ID列に作成されます。

1.8.1.3 チェーンパターン表

チェーンパターン表内の各行には、RDFグラフでの固定長のパスが含まれます。

パスは一連の2つ以上のトリプルであり、シーケンス内の最後のトリプルを除き、トリプルの目的語は次のトリプルの主語と同じです。長さnのパスが格納されているチェーンパターン表を問合せ処理中に使用して、RDF_LINK$表のcurrent_triple.object = next_triple.subjectタイプのn方向結合を単純な表参照に置き換えることができます。

たとえば、{ ?gma :motherOf ?f . ?f :fatherOf ?c }という問合せパターンの実行を高速化するには、key_stringとして指定された一連のプロパティ(' :motherOf :fatherOf ')を使用してチェーンパターン表を作成します。

表1-22に、前述のサンプル・データでのチェーンパターン表の構造と内容を示します。ここで示す3つの列には、プロパティ・チェーンを満たす2つのパス((:kathy) –[:motherOf]-> (:bob) –[:fatherOf]-> (:john)および(:alice) –[:motherOf]-> (:bob) –[:fatherOf]-> (:mary))について、変数?gma, ?f, and ?cの字句値の数値識別子がそれぞれ格納されます。

表1-22 チェーンパターンの表構造の例

START_NODE_ID P<Id(:motherOf)> P<Id(:fatherOf)>
Id(:kathy) ... Id(:bob) ... Id(:john)
Id(:kathy) ... Id(:bob) ... Id(:mary)

プロパティ・チェーンには、同じプロパティの複数出現を含めることができます。祖父を子に結び付ける次の問合せパターンを考えてみます:

{ ?gfa :fatherOf ?f . ?f :fatherOf ?c }

key_stringとして指定された一連のプロパティ' :fatherOf :fatherOf 'を使用してチェーンパターン表を作成できます。次の表に、このようなチェーン・パターン表の構造と内容を示します。'#2'という接尾辞が付いた列名は、指定されたチェーン内の:fatherOfプロパティの2回目の出現に対応しています。それには、プロパティ・チェーンを満たす2つのパス((:henry) –[:fatherOf]-> (:bob) –[:fatherOf]-> (:john)および(:henry) –[:fatherOf]-> (:bob) –[:fatherOf]-> (:mary))が格納されます。

表1-23 チェーンパターン表での単一プロパティの複数出現

START_NODE_ID P<Id(:fatherOf)> P<Id(:fatherOf)>#2
Id(:henry) ... Id(:bob) ... Id(:john)
Id(:henry) ... Id(:bob) ... Id(:mary)

プロパティ・チェーンには、逆プロパティも含まれている場合があります。たとえば、兄弟に結び付ける問合せパターン{ ?mom :motherOf ?c . ?c ^:fatherOf ?dad }を考えてみます。key_stringとして':motherOf ^:fatherOf 'を使用してチェーンパターン表を作成できます。

表1-24に、このチェーンパターン表の構造とコンテンツを示します。なお、右端の列名R<id(:fatherOf)>にある文字'R'は、その列が逆プロパティに対応していることを示しています。このチェーンパターン表を使用できることで、チェーンパターン表内の行にアクセスするだけで前述の問合せパターンを処理でき、そうでなければ必要な、RDF_LINK$の2方向結合を回避できます。

表1-24 チェーンパターン表の逆プロパティ

START_NODE_ID P<Id(:motherOf)> R<Id(:fatherOf)>
Id(:alice) ... Id(:john) ... Id(:bob)
Id(:alice) ... Id(:mary) ... Id(:bob)
Id(:kathy) ... Id(:bob) ... Id(:henry)

例1-100 チェーンパターン表の作成

次の例では、M1という名前のRDFグラフで:fatherOfプロパティの2回出現を使用して、祖父チェーンを表すチェーン・パターン表を作成します。

BEGIN
  SEM_APIS.BUILD_RESULT_TAB(
     result_tab_name    => ‘GRANDPA’
   , query_pattern_type => SEM_APIS.SPM_TYPE_PCN
   , rdf_graph_name     => 'M1'
   , key_string         => ' S :fatherOf :fatherOf '
   , prefixes           => ' PREFIX : <http://www.example.com#> ' 
   , network_owner      => 'RDFUSER'
   , network_name       => 'NET1'
  );
END;
/

チェーンパターン表の名前、構造およびデフォルト索引は、次のように記述できます:

  • チェーン・パターン表の名前は、次のテンプレートに基づいています:

    <NETWORK_NAME>#RDF_XT$PCN_<MODEL_NAME>+__<SPM_NAME>

  • NUMBER列であるSTART_NODE_IDには、チェーンパターン表内のプロパティのシーケンスにおける最初のプロパティについて、一致するトリプルの、主語ID、または逆プロパティの場合は目的語IDが格納されます。
  • チェーンパターン表でカバーされている各プロパティのn回目の出現ごとに、字句値の数値識別子をトリプルに格納するために次の列が作成されます(なお、#n接尾辞は、n > 1の場合のみ使用されます):
    • 指定されたグラフIDを格納するためのNUMBERG<Id(property)> (またはG<Id(property)>#n)
    • 目的語IDを格納するためのNUMBERP<Id(property)> (またはP<Id(property)>#n)、または逆プロパティの場合は主語IDを格納するためのR<Id(property)> (または R<Id(property)>#n)
    • (オプション)内部使用のためのその他の列
  • テンプレート<NETWORK_NAME>#RDF_XX$PCN_<MODEL_NAME>__<SPM_NAME>を使用して名付けられた一意でない索引が、START_NODE_ID 列に作成されます。
  • また、各プロパティ列に、一意でない索引が作成されます。

1.8.2 結果表の作成および管理

以降の項では、結果表を作成および管理する手順について説明します。

1.8.2.1 結果表への字句値の組込み

結果表のオブジェクトに字句の値を含めることもできます。

結果表には、デフォルトで、目的語値の数値識別子が含まれています。また、SPM表に字句値(RDF用語)を格納することで、RDF_VALUE$表との結合を伴う参照が回避されて、SPARQL問合せ処理中の字句値の取得が高速化されます。

主語の字句値、または結果表に格納されているプロパティの値を含めることにした場合は、字句プロパティ値用の新しい列がスターパターン表とチェーンパターン表に追加されます。これらの列は、RDF_VALUE$の同じ名前を持つ列に正確に対応していることに注意してください。具体的には、逆でないプロパティの字句値を結果表に含める場合、次の列が結果表に追加されます:

  • P<Id(property)>_VALUE_TYPE
  • P<Id(property)>_VNAME_PREFIX
  • P<Id(property)>_VNAME_SUFFIX
  • P<Id(property)>_LITERAL_TYPE
  • P<Id(property)>_LANGUAGE_TYPE
  • P<Id(property)>_ORDER_NUM
  • P<Id(property)>_ORDER_DATE
  • P<Id(property)>_LONG_VALUE

逆プロパティの場合、列名では先頭文字として文字'P'ではなく'R'が使用されます。主語の字句値(つまり、START_NODE_ID列に格納されている数値識別子に対応している)を含めるために追加された列の名前には、P<Id(property)>R<Id(property)>ではなく接頭辞'S'を使用します。

次の例は、例1-98の変化形であり、主語の字句値と逆:fatherOfプロパティの字句値が含まれる点が異なります。'+'記号は、結果表に格納する必要がある字句値を示すために使用されます。ここでは、key_stringパラメータで'+S'および'+^:fatherOf'が使用されているため、主語と(逆):fatherOfプロパティそれぞれのためにさらに列が追加されます。

例1-101 主語の字句値と逆プロパティの字句値の組込み

BEGIN
  SEM_APIS.BUILD_RESULT_TAB(
     query_pattern_type => SEM_APIS.SPM_TYPE_SVP
   , result_tab_name    => 'FLHF'
   , rdf_graph_name     => 'M1'
   , key_string         => ' +S :fname :lname :height +^:fatherOf '
   , prefixes           => ' PREFIX : <http://www.example.com#> ' 
   , network_owner      => 'RDFUSER'
   , network_name       => 'NET1'
  );
END;
/

結果表がすでに存在する場合は、SEM_APIS.ALTER_RESULT_TABサブプログラムを使用して、コマンド・パラメータの値として文字列‘ADD_S_VALUE’または‘ADD_VALUE’をそれぞれ使用することで、サブジェクトまたはいずれかのプロパティの字句値を含めることができます。次の例では、:lnameプロパティの字句値を含めます。(この例で示されていないコマンドDROP_S_VALUEまたはDROP_VALUEを使用すると、主語の字句値列またはプロパティの字句値列をそれぞれ削除できます。)

例1-102 プロパティの字句値を追加するためのスターパターン表の変更

BEGIN
  SEM_APIS.ALTER_RESULT_TAB(
     query_pattern_type => SEM_APIS.SPM_TYPE_SVP
   , result_tab_name    => 'FLHF'
   , rdf_graph_name     => 'M1'
   , command            => 'ADD_VALUE'
   , pred_name          => '<http://www.example.com#lname>'
   , network_owner      => 'RDFUSER'
   , network_name       => 'NET1'
  );
END;
/

1.8.2.2 結果表に対するセカンダリ索引の作成および削除

結果表のセカンダリ索引を作成および削除できます。

特定のワークロードで、結果表のデフォルト索引によってすでに提供されているもの以外のアクセス・パスを介して結果表のコンテンツにアクセスする必要がある場合は、SEM_APIS.CREATE_INDEX_ON_RESULT_TABサブプログラムを使用することで、対応するセカンダリ(B+ツリー)索引を作成できます。

次の例では、例1-101で作成したスターパターン表に対するname_idxという索引の作成を示します。key_stringパラメータ'2P 1P S'は、そのキーが、表内の2番目のプロパティ(つまり、:lname)に対応する列の(数値ID)値、表内の1番目のプロパティ(つまり、:fname)からの値、主語(つまり、START_NODE_ID列)の順に続く文字列であることを示しています。結果表内の対応する列名の形式がP<Id(property)>であるかR<Id(property)であるかにかかわらず、n番目のプロパティを示すには必ず<n>Pを使用することに注意してください。

プロパティの字句値が結果表に含まれている場合は、索引キーに、字句値のコンポーネントを格納する列が1つ以上含まれていることもあります。コンポーネントを示すには、<n><component-code>という形式を使用します。ここで、nは0 (START_NODE_IDの場合)またはターゲット・プロパティの位置であり、component codeは、表1-25で示すとおりに、含まれている値のコンポーネント名の接尾辞に基づいて決定されます。

表1-25 字句値コンポーネント列名の接尾辞からコンポーネント・コードへのマッピング

字句値コンポーネント列名の接尾辞 コンポーネント・コード
VALUE_TYPE VT
VNAME_PREFIX VP
VNAME_SUFFIX VS
LITERAL_TYPE LT
LANGUAGE_TYPE LA
ORDER_NUM VN
ORDER_DATE VD

たとえば、キー'2P 1P 2VP 0VP S'における2VPおよび0VPで示されているのは、そのキーに次の2つの列がそれぞれの位置で含まれているということです:

  1. <SPM表の2番目のプロパティの列名>_VNAME_PREFIX
  2. S_VNAME_PREFIX列(ここでのSはSPM表のゼロ番目の列、つまりSTART_NODE_ID列に対応しています)。

例1-103 結果表に対するセカンダリ(B+ツリー)索引の作成

SEM_APIS.CREATE_INDEX_ON_RESULT_TAB(
     index_name.        => ‘name_idx’
   , query_pattern_type => SEM_APIS.SPM_TYPE_SVP
   , result_tab_name    => 'FLHF'
   , rdf_graph_name     => 'M1'
   , key_string         => ' 2P 1P S '
   , network_owner      => 'RDFUSER'
   , network_name       => 'NET1'
  );
END;
/

このサブプログラムを使用して作成された索引を削除するには、SQLのDROP INDEX <index_name>コマンドを使用します。たとえば、次のようにします。

DROP INDEX name_idx;

1.8.2.3 結果表の削除

特定の結果表を削除できます。

次の例に示すように、SEM_APIS.DROP_RESULT_TABサブプログラムを使用して結果表を削除できます。

例1-104 結果表の削除

BEGIN
  SEM_APIS.DROP_RESULT_TAB(
     query_pattern_type => SEM_APIS.SPM_TYPE_SVP
   , result_tab_name    => 'FLHF'
   , rdf_graph_name     => 'M1'
   , network_owner      => 'RDFUSER'
   , network_name       => 'NET1'
  );
END;
/

ただし、result_tab_nameパラメータに特殊文字列'*'を使用すると、query_pattern_typeパラメータで指定したタイプのすべての結果表を削除できます。すべての結果表を削除するには、タイプにかかわらず、query_pattern_typeパラメータにSEM_APIS.SPM_TYPE_ALLを使用します。

1.8.2.4 インメモリー結果表

Oracle Database In-Memoryを利用すると、オプション・パラメータでINMEMORY=Tフラグを使用してインメモリー結果表を作成できます。

一般に、ディスク上の結果表は、ワークロード内の個々の問合せで一般的に発生するパターンに基づいて設計されています。結果表に問合せに不要な余分な列が含まれている場合、ディスク・スキャンのオーバーヘッドが発生する可能性があります。問合せワークロードが不明な場合や変動する場合は、すべてのプロパティを含む結果表を構築することをお薦めします。インメモリー列形式により、必要な列のみがアクセスされるようになります。すべてのプロパティを含むインメモリー結果表は1つのみ構築でき、他の結果表は許可されません。

すべてのプロパティがあるインメモリー結果表は、次の例で示すように、'INMEMORY=T'を使用して構築できます。

例1-105 メモリー内結果表の作成

前提条件である、この例で使用される表M1_PRED_INFOがすでに存在していることを確認してください。この表は、SEM_APIS.GATHER_SPM_INFOサブプログラムを使用して作成できます。

BEGIN
SEM_APIS.BUILD_RESULT_TAB(
  rdf_graph_name    =>'M1',
  pred_info_tabname =>'M1_PRED_INFO',
  pred_name	  =>NULL,
  options	    =>' INMEMORY=T ',
  degree	     =>2,
  network_owner     =>'RDFUSER',
  network_name      =>'NET1'
  );
END;
/
すべての問合せでアクセスする一連のプロパティがわかっている場合、そのセットを使用して構築されたSVP表を次のように変更することで、すべてのプロパティのサブセットを含むインメモリーSVP表を構築できます。
ALTER TABLE “MYNET#RDF_XT$SVP_M1+__SVP1” INMEMORY;

1.8.2.5 結果表のメタデータ

RDF_SPM_INFOビューを使用して、RDFグラフで定義されている結果表についてメタデータ情報を取得できます。

表1-26 述語情報表の列

列名 説明
TABLE_NAME VARCHAR2(128) SPM表の名前。
COLUMN_NAME VARCHAR2(128) SPM表内の列の名前(START_NODE_ID、またはP<id(property)>またはR<id(property)>)。
COLUMN_ID NUMBER SPM表の列リスト内でのその列の位置。
HASVALUES NUMBER(1) 値の数値識別子に加えてその字句値もSPM表に格納されているかどうかを示します。
MODEL_ID NUMBER RDFグラフの数値識別子。
MODEL_NAME VARCHAR2(128) RDFグラフの名前。

1.8.2.6 個別プロパティについて主語ごとのカーディナリティ集計を計算するためのユーティリティ・サブプログラム

SEM_APIS.GATHER_SPM_INFOプロシージャを使用すると、トリプルの述語としての用途に基づいて、RDFグラフ内の各プロパティの主語ごとのカーディナリティ情報を格納する表を作成および移入できます。

P_VALUE_ID列には、プロパティに対応する数値識別子が格納されます。逆プロパティの場合、P_VALUE_IDには、そのプロパティのIDの負の値が格納されます。

このプロパティ・カーディナリティ表は、次の表で示すような構造になっています。特定のプロパティについてMAX_CNT > 1である場合、そのプロパティは複数値です。つまり、少なくとも1つの主語リソースについて、このプロパティが、2つ以上の異なるトリプル(同じ主語と同じ述語を共有しているが異なる目的語がある)の述語として使用されています。

表1-27 述語情報表の列

列名 タイプ 説明
P_VALUE_ID NUMBER このプロパティの値ID。負の値は、プロパティを示しています。
PRED_NAME VARCHAR2(4000) このプロパティの字句値。
MIN_CNT NUMBER このプロパティについての主語ごとのカーディナリティの最小値。
MAX_CNT NUMBER このプロパティについての主語ごとのカーディナリティの最大値。
MED_CNT NUMBER このプロパティについての主語ごとのカーディナリティの中央値。
AVG_CNT NUMBER このプロパティについての主語ごとのカーディナリティの平均値。
TOT_CNT NUMBER このプロパティを述語として保持するトリプルの合計数。
INCLUDE VARCHAR2(30) 使用されていません。

サンプルRDFデータセット(「結果表のタイプ」を参照)について、カーディナリティ情報を次の表に示します。

表1-28 述語表内のカーディナリティ情報のサンプル

P_VALUE_ID PRED_NAME MIN_CNT MAX_CNT MED_CNT AVG_CNT TOT_CNT INCLUDE
Id(:fname) :fname 1 1 4 ...
Id(:lname) :lname 1 1 4 ...
Id(:height) :height 1 1 4 ...
Id(:email) :email 1 2 4 ...
Id(:fatherOf) :fatherOf 1 2 3 ...
Id(:motherOf) :motherOf 1 2 3 ...

2番目のプロシージャSEM_APIS.BUILD_RESULT_TABは、スターパターン表、トリプルパターン表、チェーンパターン表を作成および移入します。

次の例は、SEM_APIS.GATHER_SPM_INFOおよびSEM_APIS.BUILD_RESULT_TABを使用したRDFグラフの結果表のセットを示しています。これらの結果表はSPARQL問合せの実行に自動的に使用されます。この例ではSEM_MATCHを使用しますが、Apache JenaやRDFサーバーでサポートされているAPIなど、他のAPIを介して実行されるSPARQL問合せでも、結果表が自動的に使用されます。

例1-106 結果表の作成およびSPARQL問合せでのその表の使用

SQL> set echo on pages 10000 numwidth 20 lines 200 long 10000
SQL> column s format a30
SQL> column fname format a5
SQL> column lname format a5
SQL> column height format a6
SQL> column email format a25
SQL> column nick format a10
SQL> column friend format a30
SQL> column state format a5

SQL> conn rdfuser/rdfuser
Connected.

SQL> -- create an RDF network
SQL> exec sem_apis.create_rdf_network('tbs_rdf',network_owner=>'RDFUSER',network_name=>'NET1');

PL/SQL procedure successfully completed.

SQL> --move the RDF_SPM$ table and indexes defined on it to the network's tablespace
SQL> alter table NET1#RDF_SPM$ move tablespace tbs_rdf;
SQL> set serverout on;
SQL> begin
  2   for idx in (select index_name from sys.user_indexes where table_name='NET1#RDF_SPM$') loop
  3     execute immediate 'alter index "' || idx.index_name || '" rebuild tablespace TBS_RDF';
  4     sys.dbms_output.put_line('moved (rebuild) index: ' || idx.index_name);
  5   end loop;
  6 end;
  7 /
SQL> set serverout off;

SQL> -- create an RDF graph
SQL> exec sem_apis.create_rdf_graph('M1',null,null,network_owner=>'RDFUSER',network_name=>'NET1');

PL/SQL procedure successfully completed.

SQL> -- add some data: fname, lname, height, and nickName are single-valued; email and friendOf are multi-valued
SQL> begin
  2    sem_apis.update_rdf_graph('M1',
  3  	 'PREFIX    : <http://www.example.com#>
  4  	  PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
  5  	  INSERT DATA {
  6  	    :john :fname "John" ; :lname "Brown" ; :height 72
  7  		; :email "john@email-example.com", "johnnyB@email-example.com"
  8  		; :nickName "Johnny B"
  9  		; :friendOf :ann
 10  		; :address [ :addrNum 20 ; :addrStreet "Elm Street" ; :addrCityState [ :addrCity "Boston" ; :addrState "MA" ] ] .
 11  	    :ann  :fname "Ann" ; :lname "Green" ; :height 65
 12  		; :email "ann@email-example.com"
 13  		; :nickName "Annie"
 14  		; :friendOf :john, :bill
 15  		; :address [ :addrNum 10 ; :addrStreet "Main Street" ; :addrCityState [ :addrCity "New York" ; :addrState "NY" ] ] .
 16  	    :bill :fname "Bill" ; :lname "Red" ; :height 70
 17  		; :email "bill@email-example.com"
 18  		; :nickName "Billy"
 19  		; :friendOf :ann, :jane
 20  		; :address [ :addrNum 5 ; :addrStreet "Peachtree Street" ; :addrCityState [ :addrCity "Atlanta" ; :addrState "GA" ] ] .
 21  	    :jane :fname "Jane" ; :lname "Blue" ; :height 68
 22  		; :email "jane@email-example.com", "jane2@email-example.com"
 23  		; :friendOf :bill
 24  		; :address [ :addrNum 101 ; :addrStreet "Maple Street" ; :addrCityState [ :addrCity "Chicago" ; :addrState "IL" ] ] .
 25  	  }'
 26  	 ,network_owner=>'RDFUSER'
 27  	 ,network_name=>'NET1');
 28  end;
 29  /

PL/SQL procedure successfully completed.

SQL> -- create a star-pattern table for single-valued predicates :fname, :lname, :height
SQL> BEGIN
  2    SEM_APIS.BUILD_RESULT_TAB(
  3  	  query_pattern_type => SEM_APIS.SPM_TYPE_SVP
  4  	, result_tab_name    => 'fnm_lnm_hght'
  5  	, rdf_graph_name     => 'M1'
  6  	, key_string         => ' :fname :lname :height '
  7  	, prefixes           => ' PREFIX : <http://www.example.com#> '
  8  	, degree             => 2
  9  	, network_owner      => 'RDFUSER'
 10  	, network_name       => 'NET1'
 11    );
 12  END;
 13  /

PL/SQL procedure successfully completed.

SQL> -- check the star-pattern table
SQL> select * from "NET1#RDF_XT$SVP_M1+__FNM_LNM_HGHT" order by start_node_id;

       START_NODE_ID G8337314745347241189 P8337314745347241189 G7644445801044650266 P7644445801044650266 G4791477124431525340 P4791477124431525340                                                      
-------------------- -------------------- -------------------- -------------------- -------------------- -------------------- --------------------                                                      
 1399946303865654932                       2838435233532231409                       5036507830384741776                       7949294891880010615                                                      
 7024748068782994892                       9071571320455459462                       8802343394415720481                       7603694794035016230                                                      
 8531245907959123227                         50859040499294923                       9011354822640550059                       4318017261525689661                                                      
 8972322488425499169                       3239737248730612593                       6648986869806945928                       2028730158517518732                                                      

4 rows selected.

SQL> -- create a chain-pattern table for :address/:addrCityState/:addrState
SQL> BEGIN
  2    SEM_APIS.BUILD_RESULT_TAB(
  3  	  query_pattern_type => SEM_APIS.SPM_TYPE_PCN
  4  	, result_tab_name    => 'addr_state'
  5  	, rdf_graph_name     => 'M1'
  6  	, key_string         => ' S :address :addrCityState :addrState '
  7  	, prefixes           => ' PREFIX : <http://www.example.com#> '
  8  	, degree             => 2
  9  	, network_owner      => 'RDFUSER'
 10  	, network_name       => 'NET1'
 11    );
 12  END;
 13  /

PL/SQL procedure successfully completed.

SQL> -- check the chain-pattern table content
SQL> -- Note: Since generated blank node labels may differ from run to run, the 3rd and 5th column values may vary as well
SQL> select * from "NET1#RDF_XT$PCN_M1+__ADDR_STATE" order by start_node_id, 3, 5, 7;

START_NODE_ID        G5055192271510902740 P5055192271510902740 G2282073771135796724 P2282073771135796724 G594560333771551504  P594560333771551504
-------------------- -------------------- -------------------- -------------------- -------------------- -------------------- --------------------                                                      
1399946303865654932		          6519232173603163724		          2583525877732786353		           2028557412112123936
7024748068782994892		          5974521208853734660		          3828178052943534859		           7995579594576433205
8531245907959123227		          7758805114187110754		          6401534854183681859		           5359878998404290171
8972322488425499169		           875920943154203631		          3729916732662692051		           4933462079191011078

4 rows selected.

SQL> -- create triple-pattern tables for :email and :friendOf
SQL> -- :email
SQL> BEGIN
  2    SEM_APIS.BUILD_RESULT_TAB(
  3  	  query_pattern_type => SEM_APIS.SPM_TYPE_MVP
  4  	, result_tab_name    => null
  5  	, rdf_graph_name     => 'M1'
  6  	, key_string         => ' :email '
  7  	, prefixes           => ' PREFIX : <http://www.example.com#> '
  8  	, degree             => 2
  9  	, network_owner      => 'RDFUSER'
 10  	, network_name       => 'NET1'
 11    );
 12  END;
 13  /

PL/SQL procedure successfully completed.

SQL> -- check the triple-pattern table
SQL> select * from "NET1#RDF_XT$MVP_M1+_P2930492586059823454" order by start_node_id;

       START_NODE_ID G2930492586059823454 P2930492586059823454                                                                                                                                          
-------------------- -------------------- --------------------                                                                                                                                          
 1399946303865654932                       6100245385739701229                                                                                                                                          
 7024748068782994892                       2096397932624357828                                                                                                                                          
 7024748068782994892                       6480436012276020283                                                                                                                                          
 8531245907959123227                       1846003049324830366                                                                                                                                          
 8531245907959123227                       7834835188342349976                                                                                                                                          
 8972322488425499169                       7251371240613573863                                                                                                                                          

6 rows selected.

SQL> -- :friendOf
SQL> BEGIN
  2    SEM_APIS.BUILD_RESULT_TAB(
  3  	  query_pattern_type => SEM_APIS.SPM_TYPE_MVP
  4  	, result_tab_name    => null
  5  	, rdf_graph_name     => 'M1'
  6  	, key_string         => ' :friendOf '
  7  	, prefixes           => ' PREFIX : <http://www.example.com#> '
  8  	, degree             => 2
  9  	, network_owner      => 'RDFUSER'
 10  	, network_name       => 'NET1'
 11    );
 12  END;
 13  /

PL/SQL procedure successfully completed.

SQL> -- check the triple-pattern table
SQL> select * from "NET1#RDF_XT$MVP_M1+_P1285894645615718351" order by start_node_id, 3;

       START_NODE_ID G1285894645615718351 P1285894645615718351                                                                                                                                          
-------------------- -------------------- --------------------                                                                                                                                          
 1399946303865654932                       7024748068782994892                                                                                                                                          
 1399946303865654932                       8972322488425499169                                                                                                                                          
 7024748068782994892                       1399946303865654932                                                                                                                                          
 8531245907959123227                       8972322488425499169                                                                                                                                          
 8972322488425499169                       1399946303865654932                                                                                                                                          
 8972322488425499169                       8531245907959123227                                                                                                                                          

6 rows selected.

SQL> -- gather optimizer statistics on result auxiliary tables
SQL> begin
  2    sem_perf.analyze_aux_tables(
  3  	 model_name=>'M1',
  4  	 network_owner=>'RDFUSER',
  5  	 network_name=>'NET1');
  6  end;
  7  /

PL/SQL procedure successfully completed.

SQL> -- Execute a SPARQL query that uses result tables
SQL> SELECT s, fname, lname, height, email, nick, friend, state
  2  FROM TABLE(SEM_MATCH(
  3  'PREFIX : <http://www.example.com#>
  4   SELECT *
  5   WHERE {
  6  	?s :fname ?fname
  7  	 ; :lname ?lname
  8  	 ; :height ?height
  9  	 ; :email ?email
 10  	 ; :nickName ?nick
 11  	 ; :friendOf ?friend
 12  	 ; :address/:addrCityState/:addrState ?state
 13   }'
 14  ,sem_models('M1')
 15  ,null,null,null,null
 16  ,' '
 17  ,null,null
 18  ,'RDFUSER','NET1'))
 19  ORDER BY 1,2,3,4,5,6,7,8;

S                              FNAME LNAME HEIGHT EMAIL                     NICK       FRIEND                         STATE                                                                             
------------------------------ ----- ----- ------ ------------------------- ---------- ------------------------------ -----                                                                             
http://www.example.com#ann     Ann   Green 65     ann@email-example.com      Annie      http://www.example.com#bill    NY                                                                                
http://www.example.com#ann     Ann   Green 65     ann@email-example.com      Annie      http://www.example.com#john    NY                                                                                
http://www.example.com#bill    Bill  Red   70     bill@email-example.com     Billy      http://www.example.com#ann     GA                                                                                
http://www.example.com#bill    Bill  Red   70     bill@email-example.com     Billy      http://www.example.com#jane    GA                                                                                
http://www.example.com#john    John  Brown 72     john@email-example.com     Johnny B   http://www.example.com#ann     MA                                                                                
http://www.example.com#john    John  Brown 72     johnnyB@email-example.com  Johnny B   http://www.example.com#ann     MA                                                                                

6 rows selected.

SQL> -- See the relevant portion of the SQL translation showing the result table usage.
SQL> --
SQL> -- This SQL evaluates 9 triple patterns with only 4 joins
SQL> -- instead of the 8 joins that would normally be required
SQL> -- without result tables.
SQL> --
SQL> -- The star-pattern table is used for :fname, :lname, :height.
SQL> -- triple-pattern tables are used for :email and :friendOf.
SQL> -- RDFM_M1 (view of RDF_LINK$ for RDF graph M1) is used for :nickName.
SQL> -- The chain-pattern table is used for the sequence
SQL> -- :address/:addrCityState/:addrStat
SQL> SELECT sys.dbms_lob.substr(
  2  SEM_APIS.SPARQL_TO_SQL(
  3  'PREFIX : <http://www.example.com#>
  4   SELECT *
  5   WHERE {
  6  	?s :fname ?fname
  7  	 ; :lname ?lname
  8  	 ; :height ?height
  9  	 ; :email ?email
 10  	 ; :nickName ?nick
 11  	 ; :friendOf ?friend
 12  	 ; :address/:addrCityState/:addrState ?state
 13   }'
 14  ,sem_models('M1')
 15  ,null,null,null
 16  ,' '
 17  ,null,null
 18  ,'RDFUSER','NET1'), 1004, 3377) AS SQL_TRANS_PORTION
 19  FROM SYS.DUAL;

SQL_TRANS_PORTION                                                                                                                                                                                       
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SELECT SVP0.START_NODE_ID AS S$RDFVID,
SVP0.P7644445801044650266 AS LNAME$RDFVID,
MVP1.P1285894645615718351 AS FRIEND$RDFVID,
T4.CANON_END_NODE_ID AS NICK$RDFVID,
PCN0.P594560333771551504 AS STATE$RDFVID,
SVP0.P4791477124431525340 AS HEIGHT$RDFVID,
MVP0.P2930492586059823454 AS EMAIL$RDFVID,
SVP0.P8337314745347241189 AS FNAME$RDFVID,
SVP0.START_NODE_ID AS BGP$1
FROM (
SELECT * FROM "RDFUSER".NET1#RDFM_M1) T4,
"RDFUSER"."NET1#RDF_XT$SVP_M1+__FNM_LNM_HGHT" SVP0,
"RDFUSER"."NET1#RDF_XT$PCN_M1+__ADDR_STATE" PCN0,
"RDFUSER"."NET1#RDF_XT$MVP_M1+_P2930492586059823454" MVP0,
"RDFUSER"."NET1#RDF_XT$MVP_M1+_P1285894645615718351" MVP1
WHERE SVP0.P8337314745347241189 IS NOT NULL AND
SVP0.P7644445801044650266 IS NOT NULL AND
SVP0.P4791477124431525340 IS NOT NULL AND
T4.P_VALUE_ID = 2558054308995111125 AND
1=1 AND
1=1 AND
1=1 AND
SVP0.START_NODE_ID = MVP0.START_NODE_ID AND
SVP0.START_NODE_ID = T4.START_NODE_ID AND
SVP0.START_NODE_ID = MVP1.START_NODE_ID AND
SVP0.START_NODE_ID = PCN0.START_NODE_ID AND
1=1                                                                                                                                                                                                   
                                                                                                                                                                                                    
1 row selected.

例1-107 結果表への字句値の組込み

次の例では、結果表に字句値を含めます。この例は例1-106の後に続くものであることに留意してください。
SQL> conn rdfuser/rdfuser

SQL> -- Drop and recreate the FNM_LNM_HGHT SVP table, with in-line lexical values for the :fname and :height properties.
SQL> -- Check metadata for the new result table to verify that HASVALUES=1 for the two properties whose lexical values are in-lined.

SQL> exec sem_apis.drop_result_tab(sem_apis.SPM_TYPE_SVP, ' fnm_lnm_hght ', 'm1', network_owner=>'rdfuser', network_name=>'net1');

PL/SQL procedure successfully completed.

SQL> 

SQL> BEGIN
  2    SEM_APIS.BUILD_RESULT_TAB(
  3  	  query_pattern_type => SEM_APIS.SPM_TYPE_SVP
  4  	, result_tab_name    => 'fnm_lnm_hght'
  5  	, rdf_graph_name     => 'M1'
  6  	, key_string         => ' S +:fname :lname +:height '
  7  	, prefixes           => ' PREFIX : <http://www.example.com#> '
  8  	, degree             => 2
  9  	, network_owner      => 'RDFUSER'
 10  	, network_name       => 'NET1'
 11    );
 12  END;
 13  /

PL/SQL procedure successfully completed.

SQL> 
SQL> select * from net1#rdf_spm_info where table_name like '%SVP%FNM_LNM_HGHT' order by table_name, column_id;

TABLE_NAME                               COLUMN_NAME                     COLUMN_ID            HASVALUES MODEL_ID MODEL_NAME                                                                             
---------------------------------------- -------------------- -------------------- -------------------- -------- ----------                                                                             
NET1#RDF_XT$SVP_M1+__FNM_LNM_HGHT        START_NODE_ID                           1                    0        1 M1                                                                                     
NET1#RDF_XT$SVP_M1+__FNM_LNM_HGHT        P8337314745347241189                    3                    1        1 M1                                                                                     
NET1#RDF_XT$SVP_M1+__FNM_LNM_HGHT        P7644445801044650266                    5                    0        1 M1                                                                                     
NET1#RDF_XT$SVP_M1+__FNM_LNM_HGHT        P4791477124431525340                    7                    1        1 M1                                                                                     

4 rows selected.

SQL> 
SQL> -- Drop and recreate the ADDR_STATE chain-pattern table, with in-line lexical values for the :addrState property.
SQL> -- Check metadata for the new table to verify that HASVALUES=1 for the :addrState property.

SQL> exec sem_apis.drop_result_tab(sem_apis.SPM_TYPE_PCN, ' addr_state ', 'm1', network_owner=>'rdfuser', network_name=>'net1');

PL/SQL procedure successfully completed.

SQL> 
SQL> BEGIN
  2    SEM_APIS.BUILD_RESULT_TAB(
  3  	  query_pattern_type => SEM_APIS.SPM_TYPE_PCN
  4  	, result_tab_name    => 'addr_state'
  5  	, rdf_graph_name     => 'M1'
  6  	, key_string         => ' S :address :addrCityState +:addrState '
  7  	, prefixes           => ' PREFIX : <http://www.example.com#> '
  8  	, degree             => 2
  9  	, network_owner      => 'RDFUSER'
 10  	, network_name       => 'NET1'
 11    );
 12  END;
 13  /

PL/SQL procedure successfully completed.

SQL> 
SQL> select * from net1#rdf_spm_info where table_name like '%PCN%ADDR_STATE' order by table_name, column_id;

TABLE_NAME                               COLUMN_NAME                     COLUMN_ID            HASVALUES MODEL_ID MODEL_NAME                                                                             
---------------------------------------- -------------------- -------------------- -------------------- -------- ----------                                                                             
NET1#RDF_XT$PCN_M1+__ADDR_STATE          START_NODE_ID                           1                    0        1 M1                                                                                     
NET1#RDF_XT$PCN_M1+__ADDR_STATE          P5055192271510902740                    3                    0        1 M1                                                                                     
NET1#RDF_XT$PCN_M1+__ADDR_STATE          P2282073771135796724                    5                    0        1 M1                                                                                     
NET1#RDF_XT$PCN_M1+__ADDR_STATE          P594560333771551504                     7                    1        1 M1                                                                                     

4 rows selected.

SQL> 
SQL> -- Drop and recreate the triple-pattern table for the :email property (id: 2930492586059823454), with in-line lexical values for the :email property.
SQL> -- Check metadata for the new table to verify that HASVALUES=1 for the :email property.

SQL> exec sem_apis.drop_result_tab(sem_apis.SPM_TYPE_MVP, '<http://www.example.com#email>', 'm1', network_owner=>'rdfuser', network_name=>'net1');

PL/SQL procedure successfully completed.

SQL> BEGIN
  2    SEM_APIS.BUILD_RESULT_TAB(
  3  	  query_pattern_type => SEM_APIS.SPM_TYPE_MVP
  4  	, result_tab_name    => null
  5  	, rdf_graph_name     => 'M1'
  6  	, key_string         => ' +:email '
  7  	, prefixes           => ' PREFIX : <http://www.example.com#> '
  8  	, degree             => 2
  9  	, network_owner      => 'RDFUSER'
 10  	, network_name       => 'NET1'
 11    );
 12  END;
 13  /

PL/SQL procedure successfully completed.

SQL> 
SQL> select * from net1#rdf_spm_info where table_name like '%MVP%P2930492586059823454' order by table_name, column_id;

TABLE_NAME                               COLUMN_NAME                     COLUMN_ID            HASVALUES MODEL_ID MODEL_NAME                                                                             
---------------------------------------- -------------------- -------------------- -------------------- -------- ----------                                                                             
NET1#RDF_XT$MVP_M1+_P2930492586059823454 START_NODE_ID                           1                    0        1 M1                                                                                     
NET1#RDF_XT$MVP_M1+_P2930492586059823454 P2930492586059823454                    3                    1        1 M1                                                                                     

2 rows selected.

SQL> 
SQL> -- gather optimizer statistics on result auxiliary tables
SQL> begin
  2    sem_perf.analyze_aux_tables(
  3  	 model_name=>'M1',
  4  	 network_owner=>'RDFUSER',
  5  	 network_name=>'NET1');
  6  end;
  7  /

PL/SQL procedure successfully completed.

SQL> 
SQL> -- Execute a SPARQL query that uses result tables
SQL> SELECT s, fname, lname, height, email, nick, friend, state
  2  FROM TABLE(SEM_MATCH(
  3  'PREFIX : <http://www.example.com#>
  4   SELECT *
  5   WHERE {
  6  	?s :fname ?fname
  7  	 ; :lname ?lname
  8  	 ; :height ?height
  9  	 ; :email ?email
 10  	 ; :nickName ?nick
 11  	 ; :friendOf ?friend
 12  	 ; :address/:addrCityState/:addrState ?state
 13   }'
 14  ,sem_models('M1')
 15  ,null,null,null,null
 16  ,' '
 17  ,null,null
 18  ,'RDFUSER','NET1'))
 19  ORDER BY 1,2,3,4,5,6,7,8;

S                              FNAME LNAME HEIGHT EMAIL                     NICK       FRIEND                         STATE                                                                             
------------------------------ ----- ----- ------ ------------------------- ---------- ------------------------------ -----                                                                             
http://www.example.com#ann     Ann   Green 65     ann@email-example.com     Annie      http://www.example.com#bill    NY                                                                                
http://www.example.com#ann     Ann   Green 65     ann@email-example.com     Annie      http://www.example.com#john    NY                                                                                
http://www.example.com#bill    Bill  Red   70     bill@email-example.com    Billy      http://www.example.com#ann     GA                                                                                
http://www.example.com#bill    Bill  Red   70     bill@email-example.com    Billy      http://www.example.com#jane    GA                                                                                
http://www.example.com#john    John  Brown 72     john@email-example.com    Johnny B   http://www.example.com#ann     MA                                                                                
http://www.example.com#john    John  Brown 72     johnnyB@email-example.com Johnny B   http://www.example.com#ann     MA                                                                                

6 rows selected.

SQL> 
SQL> -- See the relevant portion of the SQL translation showing SPM table usage including in-line lexical values.
SQL> --
SQL> -- The number of joins with the RDF_VALUE$ table (for looking up lexical values) goes down from 8 to 4
SQL> -- because out of the 8 variables being projected, 4 -- fname, height, email, state -- appear
SQL> -- with properties whose lexical values are present in-line in the available result tables.
SQL> --
SQL> SELECT SEM_APIS.SPARQL_TO_SQL(
  2  'PREFIX : <http://www.example.com#>
  3   SELECT *
  4   WHERE {
  5  	?s :fname ?fname
  6  	 ; :lname ?lname
  7  	 ; :height ?height
  8  	 ; :email ?email
  9  	 ; :nickName ?nick
 10  	 ; :friendOf ?friend
 11  	 ; :address/:addrCityState/:addrState ?state
 12   }'
 13  ,sem_models('M1')
 14  ,null,null,null
 15  ,' '
 16  ,null,null
 17  ,'RDFUSER','NET1')
 18  FROM SYS.DUAL;

SEM_APIS.SPARQL_TO_SQL('PREFIX:<HTTP://WWW.EXAMPLE.COM#>SELECT*WHERE{?S:FNAME?FN                                                                                                                        
--------------------------------------------------------------------------------                                                                                                                        
SELECT * FROM (                                                                                                                                                                                         
SELECT … <omitted> …
FROM (SELECT … <omitted> …                                                                                                                                                                             
FROM (                                                                                                                                                                                                  
SELECT * FROM "RDFUSER".NET1#RDFM_M1) T4,                                                                                                                                                               
"RDFUSER"."NET1#RDF_XT$SVP_M1+__FNM_LNM_HGHT" SVP0,                                                                                                                                                     
"RDFUSER"."NET1#RDF_XT$PCN_M1+__ADDR_STATE" PCN0,                                                                                                                                                       
"RDFUSER"."NET1#RDF_XT$MVP_M1+_P2930492586059823454" MVP0,                                                                                                                                              
"RDFUSER"."NET1#RDF_XT$MVP_M1+_P1285894645615718351" MVP1                                                                                                                                               
WHERE 1=1 AND                                                                                                                                                                                           
1=1 AND                                                                                                                                                                                                 
1=1 AND                                                                                                                                                                                                 
1=1 AND                                                                                                                                                                                                 
SVP0.P8337314745347241189 IS NOT NULL AND                                                                                                                                                               
SVP0.P7644445801044650266 IS NOT NULL AND                                                                                                                                                               
SVP0.P4791477124431525340 IS NOT NULL AND                                                                                                                                                               
T4.P_VALUE_ID = 2558054308995111125 AND                                                                                                                                                                 
1=1 AND                                                                                                                                                                                                 
1=1 AND                                                                                                                                                                                                 
1=1 AND                                                                                                                                                                                                 
SVP0.START_NODE_ID = MVP0.START_NODE_ID AND                                                                                                                                                             
SVP0.START_NODE_ID = T4.START_NODE_ID AND                                                                                                                                                               
SVP0.START_NODE_ID = MVP1.START_NODE_ID AND                                                                                                                                                             
SVP0.START_NODE_ID = PCN0.START_NODE_ID AND                                                                                                                                                             
1=1) R, "RDFUSER".NET1#RDF_VALUE$ V0, "RDFUSER".NET1#RDF_VALUE$ V1, "RDFUSER".NET1#RDF_VALUE$ V2, "RDFUSER".NET1#RDF_VALUE$ V3                                                                                                                                                          
WHERE (1=1)  AND (R.S$RDFVID = V0.VALUE_ID) AND (R.LNAME$RDFVID = V1.VALUE_ID) AND (R.FRIEND$RDFVID = V2.VALUE_ID) AND (R.NICK$RDFVID = V3.VALUE_ID)                                                                                                                                    
) WHERE (1=1)                                                                                                                                                                                           
                                                                                                                                                                                                        

1 row selected.

SQL> 
SQL> -- In addition to value projection. In-line lexical values
SQL> -- can be used to evaluate FILTER conditions.
SQL> -- The value for ?height can be taken directly from the
SQL> -- SVP table in this case.
SQL> SELECT s, height
  2  FROM TABLE(SEM_MATCH(
  3  'PREFIX : <http://www.example.com#>
  4   SELECT ?s ?height
  5   WHERE {
  6  	?s :fname ?fname
  7  	 ; :lname ?lname
  8  	 ; :height ?height
  9  	FILTER (?height >= 72)
 10   }'
 11  ,sem_models('M1')
 12  ,null,null,null,null
 13  ,' '
 14  ,null,null
 15  ,'RDFUSER','NET1'))
 16  ORDER BY 1,2;

S                              HEIGHT                                                                                                                                                                   
------------------------------ ------                                                                                                                                                                   
http://www.example.com#john    72                                                                                                                                                                       

1 row selected.

SQL> 
SQL> -- The SQL translation shows in-line lexical value usage for ?height >= 72.
SQL> SELECT SEM_APIS.SPARQL_TO_SQL(
  2  'PREFIX : <http://www.example.com#>
  3   SELECT ?s ?height
  4   WHERE {
  5  	?s :fname ?fname
  6  	 ; :lname ?lname
  7  	 ; :height ?height
  8  	FILTER (?height >= 72)
  9   }'
 10  ,sem_models('M1')
 11  ,null,null,null
 12  ,' '
 13  ,null,null
 14  ,'RDFUSER','NET1') AS SQL_TRANS
 15  FROM SYS.DUAL;

SQL_TRANS                                                                                                                                                                                               
--------------------------------------------------------------------------------                                                                                                                        
SELECT * FROM (                                                                                                                                                                                         
SELECT … <omitted> …                                                                                                                                                                                         
FROM (SELECT …<omitted> …                                                                                                                                                                             
FROM "RDFUSER"."NET1#RDF_XT$SVP_M1+__FNM_LNM_HGHT" SVP0                                                                                                                                                 
WHERE 1=1 AND                                                                                                                                                                                           
SVP0.P8337314745347241189 IS NOT NULL AND                                                                                                                                                               
SVP0.P7644445801044650266 IS NOT NULL AND                                                                                                                                                               
SVP0.P4791477124431525340 IS NOT NULL AND                                                                                                                                                               
1=1 AND                                                                                                                                                                                                 
1=1 AND                                                                                                                                                                                                 
(SVP0.P4791477124431525340_ORDER_NUM >= to_number(72))) R, "RDFUSER".NET1#RDF_VALUE$ V0                                                                                                                                                                                                 
WHERE (1=1)  AND (R.S$RDFVID = V0.VALUE_ID)                                                                                                                                                             
) WHERE (1=1)                                                                                                                                                                                           
                                                                                                                                                                                                        

1 row selected.

SQL> 

例1-108 結果補助表でのセカンダリ索引の作成

次の例では、結果の補助表に対するセカンダリ索引の作成を示します。この例は例1-106例1-107の後に続くものであることに留意してください。

SQL> 
SQL> conn rdfuser/rdfuser
Connected.
SQL> 
SQL> -- create index on the ORDER_NUM (VN) component of the lexical value of the :height property.
SQL> -- This component is stored as a column in the FNM_LNM_HGHT SVP table.
SQL> -- It holds the numeric value for RDF literals of numeric type.
SQL> -- Since the :height property is the 3rd property in the SVP table, it is referred to using 3VN in the key_string argument below.

SQL> BEGIN
  2    SEM_APIS.CREATE_INDEX_ON_RESULT_TAB(
  3  	  index_name         => 'height_idx'
  4  	, query_pattern_type => SEM_APIS.SPM_TYPE_SVP
  5  	, result_tab_name    => 'fnm_lnm_hght'
  6  	, rdf_graph_name     => 'M1'
  7  	, key_string         => ' 3VN S '
  8  	, degree             => 2
  9  	, network_owner      => 'RDFUSER'
 10  	, network_name       => 'NET1'
 11    );
 12  END;
 13  /

PL/SQL procedure successfully completed.

SQL> 
SQL> -- EXPLAIN PLAN for the SPARQL query above involving "height >= 72" shows use of this index for access.
SQL> EXPLAIN PLAN FOR
  2  SELECT s, height
  3  FROM TABLE(SEM_MATCH(
  4  'PREFIX : <http://www.example.com#>
  5   SELECT ?s ?height
  6   WHERE {
  7  	?s :fname ?fname
  8  	 ; :lname ?lname
  9  	 ; :height ?height
 10  	FILTER (?height >= 72)
 11   }'
 12  ,sem_models('M1')
 13  ,null,null,null,null
 14  ,' '
 15  ,null,null
 16  ,'RDFUSER','NET1'))
 17  ORDER BY 1,2;

Explained.

SQL> 
SQL> select plan_table_output from table(dbms_xplan.display('plan_table',null,'basic +predicate'));

PLAN_TABLE_OUTPUT                                                                                                                                                                                       
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3046664063                                                                                                                                                                             
                                                                                                                                                                                                        
-------------------------------------------------------------------------------------                                                                                                                   
| Id  | Operation                               | Name                              |                                                                                                                   
-------------------------------------------------------------------------------------                                                                                                                   
|   0 | SELECT STATEMENT                        |                                   |                                                                                                                   
|   1 |  SORT ORDER BY                          |                                   |                                                                                                                   
|   2 |   NESTED LOOPS                          |                                   |                                                                                                                   
|   3 |    NESTED LOOPS                         |                                   |                                                                                                                   
|   4 |     VIEW                                |                                   |                                                                                                                   
|*  5 |      TABLE ACCESS BY INDEX ROWID BATCHED| NET1#RDF_XT$SVP_M1+__FNM_LNM_HGHT |                                                                                                                   
|*  6 |       INDEX RANGE SCAN                  | HEIGHT_IDX                        |                                                                                                                   
|*  7 |     INDEX UNIQUE SCAN                   | NET1#C_PK_VID                     |                                                                                                                   
|   8 |    TABLE ACCESS BY INDEX ROWID          | NET1#RDF_VALUE$                   |                                                                                                                   
-------------------------------------------------------------------------------------                                                                                                                   
                                                                                                                                                                                                        
Predicate Information (identified by operation id):                                                                                                                                                     
---------------------------------------------------                                                                                                                                                     
                                                                                                                                                                                                        
   5 - filter("SVP0"."P8337314745347241189" IS NOT NULL AND                                                                                                                                             
              "SVP0"."P7644445801044650266" IS NOT NULL AND "SVP0"."P4791477124431525340"                                                                                                               
              IS NOT NULL)                                                                                                                                                                              
   6 - access("SVP0"."P4791477124431525340_ORDER_NUM">=72 AND                                                                                                                                           
              "SVP0"."START_NODE_ID">0 AND "SVP0"."P4791477124431525340_ORDER_NUM" IS NOT                                                                                                               
              NULL)                                                                                                                                                                                     
       filter("SVP0"."START_NODE_ID">0)                                                                                                                                                                 
   7 - access("R"."S$RDFVID"="V0"."VALUE_ID")                                                                                                                                                           

27 rows selected.

SQL> 
SQL> select column_name, column_position from all_ind_columns where index_name='HEIGHT_IDX' order by 2;

COLUMN_NAME					COLUMN_POSITION
------------------------------	--------------------
P4791477124431525340_ORDER_NUM	1
START_NODE_ID			    2

1.8.2.7 結果表を含むRDFグラフに対するDML操作の実行

DML操作では、すべてのスターパターン表、トリプルパターン表、チェーンパターン表が自動的にメンテナンスされます。

  • 削除: 削除操作の場合、トリプル・パターン表から対応する行が削除されます。スターパターン表では、対応する列値は、値列を含めてNULLに設定されます。チェーンパターン表では、削除されたトリプルを使用する行は、チェーン内のリンクの削除を反映するために削除されます。
  • 挿入: 挿入操作では、新しいサブジェクト行または対応する列値がトリプルパターン表に挿入されます(値列を含む値が存在しない場合)。スターパターン表およびチェーンパターン表では、既存の値がNULLの場合、新しいサブジェクト行または列値が挿入されます。既存の値とは異なる値が挿入されると、スターパターン表の制約違反に対してエラーが発生します。

1.8.2.8 結果表を含むRDFグラフでのバルク・ロード操作の実行

RDFデータをRDFグラフにバルク・ロードするときに、そのグラフに結果表が存在する場合、それらはデータのロード前に切り捨てられ、ロード完了後に再移入されます。

1.8.2.9 結果表の統計の収集

結果表の統計を最新にすることは、優れた問合せパフォーマンスを得るために重要です。

SEM_PERF.ANALYZE_AUX_TABLESプロシージャをコールして、結果表の統計を収集できます。

1.8.3 結果表のSPARQL問合せオプション

結果表が存在する場合、SPARQL問合せは結果表を自動的に使用します。

結果表を利用するために既存のSPARQLワークロードを変更する必要はありません。ただし、結果表の使用を微調整するために、いくつかの新しい問合せオプションおよびオプティマイザ・ヒントを使用できます。

次の問合せオプションは、SEM_MATCHのoptions引数、またはApache JenaやRDFサーバーのサポートによって使用されるSEM_FS_NS接頭辞で使用できます。

  • COST_BASED_SPM_OPT - 結果表の使用方法は、問合せ実行計画のコストによって決定されます
  • DISABLE_SPM_OPT - 結果表(スターパターン、トリプルパターン、チェーンパターン)を使用しない
  • DISABLE_SVP_OPT – スターパターン表を使用しない
  • DISABLE_PCN_OPT – チェーンパターン表を使用しない
  • DISABLE_MVP_OPT – トリプルパターン表を使用しない
  • DISABLE_SPM_VALUES_OPT - 値の投影またはフィルタの評価(スターパターン、トリプルパターン、チェーンパターン)に結果表でインライン字句値を使用しない
  • DISABLE_SPM_VALUE_PROJ_OPT - 値の投影(スターパターン、トリプルパターン、チェーンパターン)に結果表でインライン字句値を使用しない
  • MIN_SVP_CLUSTER_SIZE(n) - スターパターン表に含まれるn個以上のプロパティを参照するスター・パターン・クラスタにのみスターパターン表を使用します(デフォルトではn = 1)。
  • PREFER_PCN=T - スターパターン表またはチェーンパターン表を使用してトリプルパターンを評価できる場合、チェーンパターン表を選択します(デフォルトの動作はスターパターン表を使用します)。

HINT0ヒント文字列、SEM_MATCHのoptions引数、およびApache JenaやRDFサーバーのサポートによって使用されるSEM_FS_NS接頭辞では、次の問合せオプティマイザ・ヒントを使用できます。

  • ALL_SPM_HASH / ALL_SPM_NL– 結果表を持つすべての結合(スターパターン、トリプルパターン、チェーンパターン)にハッシュ/ネステッド・ループ結合を使用します。
  • ALL_SVP_HASH / ALL_SVP_NL - スターパターン表とのすべての結合にハッシュ/ネステッド・ループ結合を使用します
  • ALL_MVP_HASH / ALL_MVP_NL - トリプルパターン表とのすべての結合にハッシュ/ネステッド・ループ結合を使用します
  • ALL_PCN_HASH / ALL_PCN_NL - チェーンパターン表とのすべての結合にハッシュ/ネステッド・ループ結合を使用します

1.8.4 結果表を使用する場合の特別な考慮事項

この項では、結果表の使用時に考慮する必要があるいくつかの制限事項を説明します。

  • 結果表は、単一のRDFグラフでのみサポートされます。RDFグラフ収集および推論グラフはサポートされていません。
  • 結果表は、Oracle Label Securityを使用しているRDFネットワークではサポートされていません。
  • フラッシュバック問合せは、結果表ではサポートされていません。
  • 結果表を含むRDFグラフは、SEM_APIS.MERGE_RDF_GRAPHS操作で宛先RDFグラフとして使用できません。
  • GeoSPARQL関数またはOracle Text関数を使用するSPARQL問合せは、結果表を使用しません。
  • +および*プロパティ・パス式の評価では結果表は使用されません。
  • 結果表は、SEM_APIS.APPEND_SEM_NETWORK_DATASEM_APIS.MOVE_SEM_NETWORK_DATAまたはSEM_APIS.RESTORE_SEM_NETWORK_DATA操作ではサポートされていません。