7.6 SPARQL問合せ処理の最適化

この項では、SPARQL問合せ処理を強化できる、support for Apache Jenaのいくつかのパフォーマンス関連機能について説明します。これらの機能は、デフォルトでは自動的に実行されます。

ここでは、CONSTRUCT機能およびプロパティ・パスなど、SPARQLについての知識があることを前提としています。

7.6.1 単一のSEM_MATCHコールへのSPARQL問合せのコンパイル

DISTINCT、OPTIONAL、FILTER、UNION、ORDER BYおよびLIMITを含むSPARQL問合せは、単一のOracle SEM_MATCH表関数に変換されます。SEM_MATCHでサポートされないSPARQL機能(CONSTRUCTなど)を使用しているために、問合せを直接SEM_MATCHに変換できない場合、support for Apache Jenaは、ハイブリッドな方法を採用し、単一のSEM_MATCH関数を使用して問合せの最も大きな部分を実行しながら、Jena ARQ問合せエンジンを使用して残りの部分の実行を試みます。

たとえば、次のSPARQL問合せは、単一のSEM_MATCH表関数に直接変換されます。

PREFIX dc:  <http://purl.org/dc/elements/1.1/> 
PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
PREFIX foaf: <http://xmlns.com/foaf/0.1/> 
SELECT ?person ?name 
  WHERE {
                 {?alice foaf:knows ?person . }
               UNION { 
                 ?person ?p ?name. OPTIONAL { ?person ?x ?name1 } 
                     }
        }

一方、次の問合せ例は、CONSTRUCTキーワードのため、単一のSEM_MATCH表関数に直接変換できません。

PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#> 
CONSTRUCT  { <http://example.org/person#Alice> vcard:FN ?obj } 
  WHERE  { { ?x <http://pred/a> ?obj.}
         UNION
         { ?x <http://pred/b> ?obj.}  }

この場合、support for Apache Jenaは、内側のUNION問合せを単一のSEM_MATCH表関数に変換し、その結果セットをさらに評価するため、Jena ARQ問合せエンジンに渡します。

7.6.2 プロパティ・パスの処理の最適化

Jenaに定義されているとおり、プロパティ・パスは2つのグラフ・ノード間でRDFグラフを介して使用可能なルートです。プロパティ・パスはSPARQLの拡張機能であり、RDFグラフのパターン・マッチングでプロパティに正規表現を使用できるため、基本的なグラフ・パターン問合せよりも表現力が豊かです。プロパティ・パスの詳細は、Jena ARQ問合せエンジンのドキュメントを参照してください。

RDF graph support for Apache Jenaは、Jena ARQ問合せエンジンとの統合によって、すべてのJenaプロパティ・パス・タイプをサポートしますが、いくつかの一般的なパス・タイプは、パフォーマンスを向上するため、ネイティブSQL階層問合せ(SEM_MATCHベースではない)に直接変換されます。次のタイプのプロパティ・パスは、トリプル・データを処理する際、support for Apache JenaによってSQLに直接変換されます。

  • 述語選択肢: (p1 | p2 | … | pn) piはプロパティURIです。

  • 述語順序: (p1 / p2 / … / pn) piはプロパティURIです。

  • 逆パス: ( ^ p ) pは述語URIです。

  • 複雑なパス: p+、p*、p{0, n} pは選択肢、順序、逆パスまたはプロパティURIです。

この文法で対応できないパス表現は、support for Apache JenaによってSQLに直接変換することができず、Jena問合せエンジンを使用して応答されます。

次の例では、パス順序を使用したプロパティ・パス表現を使用するコード・スニペットが含まれます。

String m = "PROP_PATH";
 
ModelOracleSem model = ModelOracleSem.createOracleSemModel(oracle, m);
 
GraphOracleSem graph = new GraphOracleSem(oracle, m);    
    
// populate the RDF Graph
    graph.add(Triple.create(Node.createURI("http://a"),
    Node.createURI("http://p1"),
    Node.createURI("http://b")));
 
graph.add(Triple.create(Node.createURI("http://b"),
 Node.createURI("http://p2"),
 Node.createURI("http://c")));
 
graph.add(Triple.create(Node.createURI("http://c"),
 Node.createURI("http://p5"),
 Node.createURI("http://d")));
 
String query =
" SELECT ?s  " +
" WHERE {?s (<http://p1>/<http://p2>/<http://p5>)+ <http://d>.}";
   
QueryExecution qexec = 
      QueryExecutionFactory.create(QueryFactory.create(query, 
 Syntax.syntaxARQ), model);
 
try {
  ResultSet results = qexec.execSelect();
  ResultSetFormatter.out(System.out, results);
}
finally {
  if (qexec != null)
    qexec.close();
}
     
OracleUtils.dropSemanticModel(oracle, m);
model.close();