7.7 他の機能をサポートするためのSPARQL構文への追加

RDF Graph support for Apache Jenaでは、ヒントと追加の問合せオプションを渡すことができます。問合せオプションを含むOracle固有の名前空間を使用してSPARQL名前空間接頭辞の構文をオーバーロードすることで、これらの機能を実装できます。

PREFIX ORACLE_SEM_xx_NS形式の名前空間では、xxの部分に機能の種別(ヒントならHTAPなら追加の述語など)が表されています。

7.7.1 SQLヒント

SQLヒントは、次の形式の行を含むSEM_MATCH問合せに渡すことができます。

PREFIX ORACLE_SEM_HT_NS: <http://oracle.com/semtech#hint>

ここでのhintは、SEM_MATCHによってサポートされる任意のヒントです。たとえば、次のようにします。

PREFIX ORACLE_SEM_HT_NS: <http://oracle.com/semtech#leading(t0,t1)> 
SELECT ?book ?title ?isbn     
WHERE { ?book <http://title> ?title. ?book <http://ISBN> ?isbn }

この例で、t0,t1は、問合せの1番目と2番目のパターンを指します。

SEM_MATCHと比較すると、ヒントの指定に若干違いがあることに注意してください。名前空間の値の構文の制限により、カンマ(,)は空白ではなく、t0t1(または他のヒント・コンポーネント)を区切るために使用されます。

SQLヒントの使用に関する詳細は、「SEM_MATCH表関数を使用したRDFデータの問合せ」を、特にoptions属性でのHINT0キーワードに関する資料を参照してください。

7.7.2 SPARQL問合せでのバインド変数の使用

Oracle Databaseでバインド変数を使用すると、問合せの解析時間を削減し、問合せ効率と同時実行性を向上させることができます。SPARQL問合せにおけるバインド変数のサポートは、ORACLE_SEM_FS_NSと同様の名前空間プラグマ指定を通して提供されます。

アプリケーションが2つのSPARQL問合せを実行する事例について考えます(2番目(問合せ2)は、1番目(問合せ1)の結果の一部または全部に応じて異なります)。バインド変数を必要としないいくつかの方法を次に示します。

  • 問合せ1の結果を繰り返して、1組の問合せを生成します。(ただし、この方法は、問合せ1の結果の数と同数の問合せを必要とします。)

  • 問合せ1の結果に基づいて、SPARQLフィルタ式を構築します。

  • 問合せ1を副問合せとみなします。

この場合のもう1つの方法は、次のサンプル・シナリオのように、バインド変数を使用することです。

Query 1:
 
  SELECT ?x
    WHERE { ... <some complex query> ... };
 
 
Query 2:
 
  SELECT ?subject ?x
    WHERE {?subject <urn:related> ?x .};

次の例は、support for Apache Jenaでバインド変数を使用するための構文を含む問合せ2を示します。

PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#no_fall_back,s2s>
PREFIX ORACLE_SEM_UEAP_NS: <http://oracle.com/semtech#x$RDFVID%20in(?,?,?)>
PREFIX ORACLE_SEM_UEPJ_NS: <http://oracle.com/semtech#x$RDFVID>
PREFIX ORACLE_SEM_UEBV_NS: <http://oracle.com/semtech#1,2,3>
SELECT ?subject ?x
WHERE {
  ?subject <urn:related>  ?x
};

この構文では、次の名前空間が使用されています。

  • ORACLE_SEM_UEAP_NSはORACLE_SEM_AP_NSと同様ですが、ORACLE_SEM_UEAP_NSの値の部分はURLエンコードされています。値の部分は、使用する前にURLデコードされている必要があり、それによってSPARQL問合せへの追加述語とみなされます。

    この例では、URLデコーディングの後に、このORACLE_SEM_UEAP_NS接頭辞の値部分(#文字の後)が「x$RDFVID in(?,?,?)」になります。3つの疑問符は、問合せ1の3つの値に対する暗黙的なバインディングを示します。

  • ORACLE_SEM_UEPJ_NSは、関係する追加の投影を指定します。この場合、ORACLE_SEM_UEAP_NSがx$RDFVID列(問合せのSELECT句には出現しません)を参照するため、指定する必要があります。複数の投影は、カンマで区切ります。

  • ORACLE_SEM_UEBV_NSは、最初にURLエンコードされ、次に連結されてカンマで区切られたバインド値のリストを指定します。

前述の問合せ例は、次の非SPARQL構文の問合せと概念的に同じであり、1、2および3はバインド値とみなされます。

SELECT ?subject ?x
  WHERE {
    ?subject <urn:related>  ?x
  }
  AND ?x$RDFVID in (1,2,3);

前述の問合せ2のSPARQLの例で、3つの整数1、2および3は問合せ1からのものです。oext:build-uri-for-id関数を使用して、そのような内部の整数IDをRDFリソースのために生成することができます。次の例は、問合せ1からの内部整数IDを取得します。

PREFIX oext: <http://oracle.com/semtech/jena-adaptor/ext/function#>
SELECT ?x  (oext:build-uri-for-id(?x) as ?xid)
WHERE { ... <some complex query> ... };

?xidの値は、<rdfvid:整数値>の形式です。アプリケーションは、山カッコと文字列rdfvid:を無視して整数値を取り出し、これらを問合せ2に渡します。

もう1つの例として、単一の問合せ構造だが、多数の異なる定数がある可能性がある場合について考えてみます。たとえば、次のSPARQL問合せは、趣味を持っており、アプリケーションにログインしている各ユーザーの趣味を検索します。アプリケーションのユーザーは異なるURIを使用して表現されるため、このSPARQL問合せに対して様々なユーザーから様々な<uri>値が提供されます。

SELECT ?hobby
  WHERE { <uri> <urn:hasHobby> ?hobby };

1つの方法(バインド変数を使用しない)は、異なる<uri>値ごとに異なるSPARQL問合せを生成することです。たとえば、ユーザーJane Doeが、次のSPARQL問合せの実行をトリガーするとします。

SELECT ?hobby WHERE {
<http://www.example.com/Jane_Doe> <urn:hasHobby> ?hobby };

一方、もう1つの方法は、ユーザーJane Doeを指定している次の例のように、バインド変数を使用することです。

PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#no_fall_back,s2s>
PREFIX ORACLE_SEM_UEAP_NS: <http://oracle.com/semtech#subject$RDFVID%20in(ORACLE_ORARDF_RES2VID(?))>
PREFIX ORACLE_SEM_UEPJ_NS: <http://oracle.com/semtech#subject$RDFVID>
PREFIX ORACLE_SEM_UEBV_NS: <http://oracle.com/semtech#http%3a%2f%2fwww.example.com%2fJohn_Doe>
SELECT ?subject ?hobby
  WHERE {
    ?subject <urn:hasHobby>  ?hobby
  };

前述の問合せ例は、次の非SPARQL構文の問合せと概念的に同じであり、http://www.example.com/Jane_Doeはバインド変数とみなされます。

SELECT ?subject ?hobby
WHERE {
  ?subject <urn:hasHobby>  ?hobby
}
AND ?subject$RDFVID in (ORACLE_ORARDF_RES2VID('http://www.example.com/Jane_Doe'));

この例で、ORACLE_ORARDF_RES2VIDは、URIとリテラルを内部整数ID表現に変換する関数です。この関数が自動的に作成されるのは、Oracleデータベースに接続するためにsupport for Apache Jenaが使用されるときです。

7.7.3 追加のWHERE句述語

SEM_MATCH filter属性に、WHEREキーワードのないWHERE句の形式の文字列として、追加の選択基準を指定することができます。次の形式の1行を含めることで、追加のWHERE句述語をSEM_MATCH問合せに渡すことができます。

PREFIX ORACLE_SEM_AP_NS: <http://oracle.com/semtech#pred>

predは、問合せに追加されるWHERE句の内容を反映します。たとえば、次のようにします。

PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX ORACLE_SEM_AP_NS:<http://www.oracle.com/semtech#label$RDFLANG='fr'>  
SELECT DISTINCT ?inst ?label
  WHERE { ?inst a <http://someCLass>. ?inst rdfs:label ?label . }
  ORDER BY (?label) LIMIT 20

この例では、ラベル変数の言語形式が'fr'である必要がある問合せに、制限事項が追加されます。

7.7.4 追加の問合せオプション

追加の問合せオプションは、次の形式の行を含むSEM_MATCH問合せに渡すことができます。

PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#option>

optionは、問合せに追加される問合せオプション(またはカンマで区切られた複数の問合せオプション)を反映します。たとえば、次のようにします。

PREFIX ORACLE_SEM_FS_NS:   
<http://oracle.com/semtech#timeout=3,dop=4,INF_ONLY,ORDERED,ALLOW_DUP=T>
SELECT * WHERE {?subject ?property ?object }

次の問合せオプションがサポートされています。

  • ALLOW_DUP=tは、結果が重複する場合がありますが、複数のRDFグラフを問い合せるための、より高速な方法です。

  • BEST_EFFORT_QUERY=tが、TIMEOUT=nオプションとともに使用されると、SPARQL問合せに対して、n秒以内に検出されるすべての一致が返されます。

  • DEGREE=nは、問合せに対して並列度(n)を文レベルで指定します。マルチコアまたはマルチCPUのプロセッサで、異なるDOP値(4または8など)を試すと、パフォーマンスが向上する場合があります。

    DEGREEと比較すると、DOPはセッション・レベルで並列度を指定します。DEGREEDOPよりも処理オーバーヘッドが少ないため、support for Apache Jenaでの使用にはDEGREEが推奨されます。

  • DOP=nは、問合せに対して並列度(n)をセッション・レベルで指定します。マルチコアまたはマルチCPUのプロセッサで、異なるDOP値(4または8など)を試すと、パフォーマンスが向上する場合があります。

  • FETCH_SIZE=nは、JDBCフェッチ・サイズ・パラメータ(データベースとの1回の通信で結果セットから読み取ってメモリーに格納する行数)を指定します。このパラメータを使用してパフォーマンスを向上させることができます。値を大きくすると、すべての結果を取得するのに必要なデータベースとの通信回数が減少します。デフォルト値は1000です。

  • INF_ONLYを指定すると、推論されたモデルのみが問い合せられます。

  • JENA_EXECUTORは、SEM_MATCH (またはネイティブSQL)に対してSPARQL問合せのコンパイルを無効にし、かわりにJenaネイティブ問合せエグゼキュータが使用されます。

  • JOIN=nは、SPARQL SERVICEコールからフェデレーテッド問合せへの結果を、どのように問合せの他の部分と結合できるかを指定します。フェデレーテッド問合せとJOINオプションに関する詳細は、「JOINオプションとフェデレーテッド問合せ」を参照してください。

  • NO_FALL_BACKは、SQL例外が発生したときに、基礎となる問合せ実行エンジンがJena実行メカニズムにフォール・バックしないようにします。

  • ODS=nは、動的なサンプリングのレベルを、文レベルで指定します。(動的なサンプリングの説明については、『Oracle Database SQLチューニング・ガイド』の動的なサンプリングによる統計の見積りに関する説明を参照してください。)nの有効値は、1から10までです。たとえば、複雑な問合せにはODS=3を試すことができます。

  • ORDEREDは、最後に必要なRDF_VALUE$結合を実行している間、問合せトリプル・パターン結合のために主要なSQLヒントに変換されます。

  • PLAIN_SQL_OPT=Fは問合せを直接SQLにネイティブ・コンパイルする機能を無効にします。

  • QID=nは、問合せID番号を指定します。この機能は、問合せに応答がない場合、その問合せを取り消すために使用できます。

  • RESULT_CACHEは、問合せにOracle RESULT_CACHEディレクティブを使用します。

  • REWRITE=Fは、SEM_MATCH表関数に対してODCI_Table_Rewriteを無効にします。

  • S2S (SPARQL to pure SQL)は、基礎となるSEM_MATCHベースの問合せ、またはSPARQL問合せに基づいて生成された問合せを、SEM_MATCH表関数を使用しないで、さらにSQL問合せに変換します。結果として生成されたSQL問合せはOracleコストベース・オプティマイザによって実行され、その結果はクライアントに渡される前にsupport for Apache Jenaによって処理されます。S2Sオプションの利点と使用方法などの詳細は、「S2Sオプションの利点と使用方法の情報」を参照してください。

    S2Sは、すべてのSPARQL問合せについてデフォルトで使用可能です。S2Sを無効にするには、次のJVMシステム・プロパティを設定します。

    -Doracle.spatial.rdf.client.jena.defaultS2S=false
    
  • SKIP_CLOB=Tは、問合せに対してCLOB値が戻されないようにします。

  • STRICT_DEFAULT=Fは、デフォルトのグラフがトリプルを名前付きグラフに含められるようにします。デフォルトでは、STRICT_DEFAULT=Tは、データセット情報が指定されない場合に、デフォルト・グラフを名前なしトリプルに制限します。

  • TIMEOUT=n(問合せタイムアウト)は、問合せが、終了されるまで実行する秒数(n)を指定します。SPARQL問合せから生成される基礎となるSQLは、多数の一致を戻し、副問合せおよび割当てと同様の機能を使用することができ、これらのすべてには、多くの時間がかかることがあります。TIMEOUTBEST_EFFORT_QUERY=tオプションは、問合せに過度な処理時間がかからないようにするために使用できます。

7.7.4.1 JOINオプションとフェデレーテッド問合せ

SPARQLフェデレーテッド問合せは、W3Cドキュメントの説明のとおり、分散データ上の問合せであり、そのために、1つのソースを問い合せて、取得した情報を使用して次のソースの問合せを制約します。詳細は、『SPARQL 1.1フェデレーテッド問合せ』 (http://www.w3.org/2009/sparql/docs/fed/service)を参照してください。

JOINオプション(「追加の問合せオプション」を参照)とSERVICEキーワードは、Support for Apache Jenaを使用するフェデレーテッド問合せで使用できます。たとえば、次の問合せを考えてみます。

SELECT ?s ?s1 ?o
 WHERE { ?s1 ?p1 ?s .
                    {
                     SERVICE <http://sparql.org/books> { ?s ?p ?o }
                    }
                 }

ローカルの問合せ部分(?s1 ?p1 ?s,)が非常に選択的である場合、次の問合せに示すように、join=2を指定します。

PREFIX ORACLE_SEM_FS_NS:   <http://oracle.com/semtech#join=2>
SELECT ?s ?s1 ?o
 WHERE { ?s1 ?p1 ?s .
                    {
                     SERVICE <http://sparql.org/books> { ?s ?p ?o }
                    }
                 }

この場合、ローカルの問合せ部(?s1 ?p1 ?s,)は、Oracle Databaseに対してローカルに実行されます。その後、結果からの?sの各バインディングは、SERVICE部分(リモート問合せ部)にプッシュされ、コールはエンドポイントが指定したサービスに行われます。この方法は、概念的にはネステッド・ループ結合と似ています。

リモート問合せ部(?s ?s1 ?o)が非常に選択的である場合、次の問合せに示すように、join=3を指定することで、リモート部分は最初に実行され、結果はローカルの部分の実行をドライブするために使用されます。

PREFIX ORACLE_SEM_FS_NS:   <http://oracle.com/semtech#join=3>
SELECT ?s ?s1 ?o
 WHERE { ?s1 ?p1 ?s .
                    {
                     SERVICE <http://sparql.org/books> { ?s ?p ?o }
                    }
                  }

この場合、単一のコールは遠隔サービス・エンドポイントに対して行われ、?sの各バインディングは、ローカルの問合せをトリガーします。join=2と同様に、この方法は概念的にはネステッド・ループベースの結合ですが、違いは順序が切り替えられるということです。

ローカルの問合せ部もリモートの問合せ部もあまり選択的でない場合、次の問合せに示すように、join=1を選択できます。

PREFIX ORACLE_SEM_FS_NS:   <http://oracle.com/semtech#join=1>
SELECT ?s ?s1 ?o
 WHERE { ?s1 ?p1 ?s .
                    {
                     SERVICE <http://sparql.org/books> { ?s ?p ?o }
                    }
                }

この場合、リモートの問合せ部とローカルの部分は独立して実行され、結果はJenaによって結合されます。この方法は、概念的にはハッシュ結合と似ています。

フェデレーテッド問合せをデバッグまたはトレースするには、Oracle JDeveloperのHTTPアナライザを使用して、基礎となるSERVICEコールを調べます。

7.7.4.2 S2Sオプションの利点と使用方法の情報

S2Sオプション(「追加の問合せオプション」参照)には、潜在的に次の利点があります。

  • RESULT_CACHEオプションと連携し、問合せパフォーマンスを向上します。S2SRESULT_CACHEオプションを使用すると、特に、頻繁に実行される問合せに有用です。

  • SEM_MATCH表関数の解析時間を削減し、多くの動的に生成されたSPARQL問合せを含むアプリケーションに有用です。

  • 問合せ本体の4000バイトの制限(SEM_MATCH表関数の最初のパラメータ)を除外し、より長く複雑な問合せがサポートされます。

S2Sオプションは、内部のインメモリー・キャッシュを、変換されたSQL問合せ文で使用されるようにします。この内部キャッシュのデフォルト・サイズは1024(つまり1024のSQL問合せ)ですが、サイズは、次のJava VMプロパティを使用して調整できます。

-Doracle.spatial.rdf.client.jena.queryCacheSize=<size>

7.7.5 中間層リソース・キャッシング

RDFデータが格納されると、すべてのリソース値がIDにハッシュされ、トリプル表に格納されます。値IDからの完全なリソース値へのマッピングは、RDF_VALUE$表に格納されます。問合せ時、選択された変数ごとにOracle DatabaseでRDF_VALUE$表による結合を実行し、リソースを取得する必要があります。

ただし、結合の数を減らすため、中間層キャッシュ・オプションを使用して、値IDとリソース値の間のマッピングを格納するために中間層でのインメモリー・キャッシュが使用されるようにできます。この機能を使用するには、SPARQL問合せに次のPREFIXプラグマを含めます。

PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#midtier_cache>

インメモリー・キャッシュの最大サイズ(バイト)を制御するには、oracle.spatial.rdf.client.jena.cacheMaxSizeシステム・プロパティを使用します。デフォルトの最大キャッシュ・サイズは、1GBです。

中間層リソース・キャッシングは、ORDER BYまたはDISTINCT(あるいは両方とも)構造体を使用した問合せ、または複数の投影変数による問合せに最も効果的です。中間層キャッシュは、「追加の問合せオプション」で指定したその他のオプションと組み合せることができます。

RDFグラフのすべてのリソースをキャッシュに事前挿入するには、GraphOracleSem.populateCacheメソッドまたはDatasetGraphOracleSem.populateCacheメソッドを使用します。どちらのメソッドも、内部の中間層キャッシュを構築するために使用されるスレッドの数を指定するパラメータをとります。どちらかのメソッドをパラレルに実行すると、複数のCPU(コア)を搭載したマシンで、パフォーマンスを構築しているキャッシュを大幅に増やすことができます。