8.6 SPARQL問合せの実行モデル

Oracle RDF Graph Adapter for Eclipse RDF4J APIを介して実行されるSPARQL問合せは、RDFデータを格納するためのOracleのリレーショナル・スキーマに対するSQL問合せとして実行されます。

OracleのSQLエンジンを使用すると、SPARQL問合せの実行で、パラレル問合せ実行、インメモリー列表現、Exadataスマート・スキャンなどの多くのパフォーマンス機能を利用できます。

SPARQL問合せを実行するには、次の2つの方法があります。

  • Queryまたはそのサブインタフェースのいずれかの実装を、基礎となるOracleSailConnectionを持つRepositoryConnectionprepareQuery関数から取得できます。

  • TupleExprのOracle固有の実装をOracleSPARQLParserから取得し、OracleSailConnectionevaluateメソッドをコールできます。

次のコード・スニペットは、最初の方法を示しています。

//run a query against the repository
String queryString = 
  "PREFIX ex: <http://example.org/ontology/>\n" + 
  "SELECT * WHERE {?x ex:name ?y} LIMIT 1 ";
TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);

try (TupleQueryResult result = tupleQuery.evaluate()) {
  while (result.hasNext()) {
    BindingSet bindingSet = result.next();
    psOut.println("value of x: " + bindingSet.getValue("x"));
    psOut.println("value of y: " + bindingSet.getValue("y"));
  }
}

OracleSailConnectionで問合せが評価されるときに、まずそのSPARQL問合せが同等のSQL問合せに変換されます。それが、その後、データベース・サーバーで実行されます。デフォルトでは、この問合せはクライアントでJavaコードを使用して変換されます。ただし、このSPARQLからSQLへの変換では、システム・プロパティoracle.rdf4j.adapter.sparqlInClientが値Fに設定されている場合は、かわりにデータベース・サーバーでSEM_APIS.SPARQL_TO_SQLストアド・プロシージャを使用できます。SEM_APIS.SPARQL_TO_SQLを使用すると、データベースのラウンドトリップが減少し、クライアントとデータベース・サーバーの間の待機時間が長い場合はパフォーマンスが向上する可能性があります。SQL問合せの結果は、標準のRDF4J問合せ結果インタフェースのいずれかを介して処理され、戻されます。

8.6.1 BIND値の使用

Oracle RDF Graph Adapter for Eclipse RDF4Jでは、Queryインタフェースで定義されたsetBindingプロシージャなど、標準のRDF4Jバインド値APIを介してバインド値がサポートされます。Oracleでは、元のSPARQL問合せ文字列にSPARQL BIND句を追加することでバインド値を実装します。

たとえば、次のSPARQL問合せについて考えます。
SELECT * WHERE { ?s <urn:fname> ?fname }
前述の問合せでは、問合せ変数?sに値<urn:john>を設定できます。この場合、変換後の問合せは次のようになります。
SELECT * WHERE { BIND (<urn:john> AS ?s) ?s <urn:fname> ?fname }

ノート:

このアプローチは、SPARQLの標準の変数スコープ・ルールに従います。したがって、最も外側のグラフ・パターンで認識されない問合せ変数(副問合せから投影されない変数など)は、バインド値に置換できません。

8.6.2 JDBC BIND値の使用

Oracle RDF Graph Adapter for Eclipse RDF4Jを使用すると、SPARQL問合せに対して実行される基礎となるSQL文でJDBCバインド値を使用できます。JDBCバインド値の実装は、前の項で説明した標準のRDF4Jバインド値のサポートよりもはるかに高性能です。

JDBCバインド値のサポートでは、標準のRDF4J setBinding APIが使用されますが、バインド変数は特定の方法で宣言する必要があり、特別な問合せオプションをORACLE_SEM_SM_NSネームスペース接頭辞とともに渡す必要があります。問合せに対してJDBCバインド変数を有効にするには、ORACLE_SEM_SM_NSネームスペース接頭辞(PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#USE_BIND_VAR=JDBC>など)にUSE_BIND_VAR=JDBCを含める必要があります。SPARQL問合せにこの問合せオプションが含まれる場合、単純なSPARQL BIND句に表示されるすべての問合せ変数が、対応するSQL問合せでJDBCバインド値として処理されます。単純なSPARQL BIND句が、BIND (<constant> as ?var)の形式(BIND("dummy" AS ?bindVar1など)を持つものです。

次のコード・スニペットは、JDBCバインド値の使用方法を示しています。

例8-4 JDBCバインド値の使用

// query that uses USE_BIND_VAR=JDBC option and declares ?name as a JDBC bind variable
String queryStr = 
  "PREFIX ex: <http://example.org/>\n"+
  "PREFIX foaf: <http://xmlns.com/foaf/0.1/>\n"+
  "PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#USE_BIND_VAR=JDBC>\n"+
  "SELECT ?friend\n" +
  "WHERE {\n" +
  "  BIND(\"\" AS ?name)\n" +
  "  ?x foaf:name ?name\n" +
  "  ?x foaf:knows ?y\n" +
  "  ?y foaf:name ?friend\n" +
  "}";

// prepare the TupleQuery with JDBC bind var option
TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryStr);

// find friends for Jack
tupleQuery.setBinding("name", vf.createLiteral("Jack");

try (TupleQueryResult result = tupleQuery.evaluate()) {
  while (result.hasNext()) {
    BindingSet bindingSet = result.next();
    System.out.println(bindingSet.getValue("friend").stringValue());
  }
}

// find friends for Jill
tupleQuery.setBinding("name", vf.createLiteral("Jill");

try (TupleQueryResult result = tupleQuery.evaluate()) {
  while (result.hasNext()) {
    BindingSet bindingSet = result.next();
    System.out.println(bindingSet.getValue("friend").stringValue());
  }
}

ノート:

Oracle RDF Graph Adapter for Eclipse RDF4JのJDBCバインド値機能は、SEM_APIS.SPARQL_TO_SQLのバインド変数機能を使用します(SEM_APIS.SPARQL_TO_SQLによるバインド変数の使用を参照)。

8.6.2.1 JDBCバインド値のサポートの制限

JDBCバインド値をサポートしているのは、SPARQL SELECTおよびASK問合せのみです。

JDBCバインド値のサポートには、次の制限があります。

  • JDBCバインド値は次ではサポートされていません。
    • SPARQL CONSTRUCT問合せ
    • DESCRIBE問合せ
    • SPARQL更新文
  • 4000文字を超える長さのRDFロング・リテラル値は、JDBCバインド値として使用できません。
  • 空白のノードは、JDBCバインド値として使用できません。

8.6.3 他の機能をサポートするためのSPARQL問合せ構文への追加

Oracle RDF Graph Adapter for Eclipse RDF4Jでは、問合せを生成および実行するためのオプションを渡すことができます。問合せオプションを含むOracle固有の名前空間を使用してSPARQL名前空間接頭辞の構文をオーバーロードすることで、これらの機能を実装できます。名前空間の形式はPREFIX ORACLE_SEM_xx_NSで、xxは機能のタイプ(SM - SEM_MATCHなど)を示します。

8.6.3.1 問合せの実行オプション

次の形式のSPARQL PREFIXを含めることで、問合せの実行オプションをデータベース・サーバーに渡すことができます。
PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#option>
前述のSPARQL PREFIXoptionは、問合せの実行時に使用される問合せオプション(またはカンマで区切られた複数のオプション)を反映します。

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

  • DOP=n: 問合せに対する並列度(n)を指定します。
  • ODS=n: 実行計画の生成時に使用するオプティマイザ動的サンプリングのレベルを指定します。

次の問合せ例では、ORACLE_SEM_FS_NS接頭辞を使用して、問合せの実行に並列度4を使用することを指定しています。

PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#dop=4>
PREFIX ex: <http://www.example.com/>
SELECT *
WHERE {?s ex:fname ?fname ;                     
          ex:lname ?lname ;                     
          ex:dob ?dob}

8.6.3.2 SPARQL_TO_SQL (SEM_MATCH)のオプション

次の形式のSPARQL PREFIXを含めることで、SPARQL_TO_SQLオプションをデータベース・サーバーに渡し、SPARQL問合せに対して生成されるSQLに影響を与えることができます。

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

前述のPREFIXoptionは、問合せの実行時に使用されるSPARQL_TO_SQLオプション(またはカンマで区切られた複数のオプション)を反映します。

使用可能なオプションの詳細は、SEM_MATCH表関数を使用したRDFデータの問合せを参照してください。この接頭辞では、SEM_MATCHまたはSEM_APIS.SPARQL_TO_SQLのオプション引数に有効としてリストされている任意の有効なキーワードまたはキーワード値ペアを使用できます。

次の問合せ例では、ORACLE_SEM_SM_NS接頭辞を使用して、問合せ内のすべてのトリプル・パターンを結合するためにHASH結合を使用するように指定します。

PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#all_link_hash>
PREFIX ex: <http://www.example.org/>
SELECT *
WHERE {?s ex:fname ?fname ;
          ex:lname ?lname ;
          ex:dob ?dob}

8.6.4 SPARQL問合せのサポートで特に留意する点

この項では、SPARQL問合せのサポートで特に留意する点について説明します。

無制限のプロパティ・パス問合せ

デフォルトでは、Oracle RDF Graph Adapter for Eclipse RDF4Jは、無制限のSPARQLプロパティ・パス演算子+および*の評価を最大10回の繰返しに制限します。これは、all_max_pp_depth(n) SPARQL_TO_SQLオプションを使用して制御できます。nは、+または*と一致する場合に許可される最大反復回数です。値をゼロに指定すると、最大反復回数は無制限になります。

次の例では、完全に無制限の検索にall_max_pp_depth(0)を使用します。
PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#all_max_pp_depth(0)>
PREFIX ex: <http://www.example.org/>
SELECT (COUNT(*) AS ?cnt)
WHERE {ex:a ex:p1* ?y}

SPARQLデータセットの指定

Eclipse RDF4J用のアダプタでは、SPARQL問合せ文字列の外部でデータセットを指定できません。OperationsetDataset()メソッドとそのサブインタフェースによるデータセットの指定はサポートされておらず、SailConnectionevaluateメソッドへのデータセット・オブジェクトの受渡しもサポートされていません。かわりに、SPARQL句FROMおよびFROM NAMEDを使用して、SPARQL問合せ文字列自体で問合せデータセットを指定します。

問合せタイムアウト

OperationおよびそのサブインタフェースでのsetMaxExecutionTimeメソッドによる問合せタイムアウトはサポートされていません。

ロングRDFリテラル

長さが4000バイトを超えるラージRDFリテラル値は、一部のSPARQL問合せ関数ではサポートされていません。詳細は、SEM_MATCH使用時の特別な考慮事項を参照してください。