7.15 その他の推奨事項とガイドライン

この項では、SPARQL問合せに関連する様々な推奨事項およびその他の情報について説明します。

7.15.1 EXISTSまたはNOT EXISTSにかわるBOUNDまたは!BOUNDの使用

パフォーマンスをさらに向上するには、EXISTSNOT EXISTSのかわりに、BOUND!BOUNDを使用します。

7.15.2 SPARQL 1.1のSELECT式

関数が現在Oracle Databaseでサポートされていなくても、パフォーマンスに大きなオーバーヘッドを発生させることなく、SPARQL 1.1のSELECT表現を使用できます。例には次のものがあります。

-- Query using SHA1 function
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>
PREFIX eg:   <http://biometrics.example/ns#>
SELECT ?name ?email (sha1(?email) as ?sha1) 
WHERE 
{ 
  ?x foaf:name  ?name ; eg:email ?email .
}

-- Query using CONCAT function
PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
SELECT ( CONCAT(?G, " ", ?S) AS ?name )
WHERE  
{ 
  ?P foaf:givenName ?G ; foaf:surname ?S 
}

7.15.3 bnode(空白ノード)を含む構文

bnodeを含む構文を問合せパターンの中で自由に使用できます。たとえば、次のbnode関連の構文はパーサー・レベルでサポートされるため、各構文はそのトリプル問合せパターンベースの完全なバージョンと同等です。

:x :q [ :p "v" ] .
 
(1 ?x 3 4) :p "w" .
 
(1 [:p :q] ( 2 ) ) .

7.15.4 SERVICE句の制限

SPARQL 1.1のフェデレーテッド問合せを記述する際に、SERVICE句内の副問合せで戻される行に対して制限を設定できます。これによって、ローカルのリポジトリとリモートのSPARQLエンドポイントの間で転送されるデータ量を効果的に制限できます。

たとえば、次の問合せでは、SERVICE句の副問合せでlimit 100を指定しています。

PREFIX : <http://example.com/>
SELECT ?s ?o 
 WHERE 
     { 
       ?s :name "CA"  
       SERVICE <http://REMOTE_SPARQL_ENDPOINT_HERE>
          {
             select ?s  ?o 
                 {?s :info ?o} 
              limit 100 
           } 
     }

7.15.5 OracleGraphWrapperForOntModelクラスによるパフォーマンス向上

Jena OntModelクラスを使用すると、Jenaモデルに格納されているオントロジを作成、変更および分析できます。ただし、OntModelの実装は、データベースに格納されているRDFデータにとって最適とはいえません。OracleモデルでOntModelを使用する場合は、次善のパフォーマンスとなります。そのため、クラスOracleGraphWrapperForOntModelは、このようなパフォーマンスの問題を軽減するために作成されました。

OracleGraphWrapperForOntModelクラスは、Jena Graphインタフェースを実装し、Jena OntModel APIで使用するためのOracle RDF/OWLグラフに基づくグラフを表します。OracleGraphWrapperForOntModelクラスは、問合せに対する持続的な変更と応答のため、2つのRDFストアを組み合せて使用します。両方のRDFストアに同じデータが含まれますが、一方はメモリーに存在し、他方はOracle Databaseに存在します。

OntModelを介して問合せがあると、OracleGraphWrapperForOntModelグラフは、パフォーマンスを向上するためにインメモリー・ストアに対して問合せを実行します。ただしOracleGraphWrapperForOntModelクラスでは、クラスの追加または削除など、両方のストアに変更を適用することによって、OntModelを介して変更を行います。

ハイブリッドな方法であることから、OracleGraphWrapperForOntModelグラフでは、メモリーにオントロジのコピーを格納するため、十分なメモリーがJVMに割り当てられている必要があります。内部の実験では、およそ3,000,000のトリプルによるオントロジで、6GB以上の物理メモリーを必要とすることが分かっています。

例7-15 OntModelとOracle Databaseに格納されたオントロジの使用

例7-15では、OntModel APIとOracleモデルに格納されている既存のオントロジを使用する方法を表示します

// Set up connection to Oracle RDF store and the Oracle model
// containing the ontology
Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
GraphOracleSem oracleGraph = new GraphOracleSem(oracle, szModelName);
 
// Create a new hybrid graph using the oracle graph to persist
// changes.  This method will copy all the data from the oracle graph
// into an in-memory graph, which may significantly increase JVM memory
// usage.
Graph hybridGraph = OracleGraphWrapperForOntModel.getInstance(oracleGraph);
 
// Build a model around the hybrid graph and wrap the model with Jena's
// OntModel
Model model = ModelFactory.createModelForGraph(hybridGraph);
OntModel ontModel = ModelFactory.createOntologyModel(ontModelSpec, model);
 
// Perform operations on the ontology
OntClass personClass = ontModel.createClass("<http://someuri/person>");
ontModel.createIndividual(personClass);
 
// Close resources (will also close oracleGraph)!
hybridGraph.close();
ontModel.close();

OracleGraphWrapperForOntModelを使用して作成されたOntModelオブジェクトは、(別のOntModel、または同じ基礎となるモデルを参照する別のOracleグラフを介した)別のプロセスによって行われた、基礎となるOracleモデルへの変更を反映しません。オントロジへのすべての変更は、グラフが閉じられるまで、単一のOntModelオブジェクトと、その基礎となるOracleGraphWrapperForOntModelグラフを介して実行される必要があります。

例7-16 カスタム・インメモリー・グラフの使用

OracleGraphWrapperForOntModelによって使用されるデフォルトのインメモリーRDFストアが、オントロジとシステムにとって十分ではない場合、インメモリー・ストアとして使用するカスタム・グラフを指定するためのインタフェースが、クラスによって提供されます。例7-16に、カスタム・インメモリー・グラフを使用してOntModelからの問合せに応答するOracleGraphWrapperForOntModelを作成する方法を示します。

// Set up connection to Oracle RDF store and the Oracle model
// containing the ontology
Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
GraphOracleSem oracleGraph = new GraphOracleSem(oracle, szModelName);
 
// Create a custom in-memory graph to use instead of the default
// Jena in-memory graph for quickly answering OntModel queries.
// Note that this graph does not *need* to be in-memory, but in-memory
// is preferred.
GraphBase queryGraph = new CustomInMemoryGraphImpl();
 
// Create a new hybrid graph using the oracle graph to persist
// changes and the custom in-memory graph to answer queries. 
// Also set the degree of parallelism to use when copying data from
// the oracle graph to the querying graph.
int degreeOfParallelism = 4;
Graph hybridGraph = OracleGraphWrapperForOntModel.getInstance(oracleGraph, queryGraph, degreeOfParallelism);
 
// Build a model and wrap the model with Jena's OntModel
Model model = ModelFactory.createModelForGraph(hybridGraph);
OntModel ontModel = ModelFactory.createOntologyModel(ontModelSpec, model);
 
// Perform operations on the ontology
// ...
 
// Close resources (will close oracleGraph and queryGraph)!
hybridGraph.close();
ontModel.close();