7.15 Other Recommendations and Guidelines
This section contains various recommendations and other information related to SPARQL queries.
- BOUND or !BOUND Instead of EXISTS or NOT EXISTS
- SPARQL 1.1 SELECT Expressions
- Syntax Involving Bnodes (Blank Nodes)
- Limit in the SERVICE Clause
- OracleGraphWrapperForOntModel Class for Better Performance
Parent topic: RDF Graph Support for Apache Jena
7.15.1 BOUND or !BOUND Instead of EXISTS or NOT EXISTS
For better performance, use BOUND
or !BOUND
instead of EXISTS
or NOT EXISTS
.
Parent topic: Other Recommendations and Guidelines
7.15.2 SPARQL 1.1 SELECT Expressions
You can use SPARQL 1.1 SELECT expressions without any significant performance overhead, even if the function is not currently supported within Oracle Database. Examples include the following:
-- 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 }
Parent topic: Other Recommendations and Guidelines
7.15.3 Syntax Involving Bnodes (Blank Nodes)
Syntax involving bnodes can be used freely in query patterns. For example, the following bnode-related syntax is supported at the parser level, so each is equivalent to its full triple-query-pattern-based version.
:x :q [ :p "v" ] . (1 ?x 3 4) :p "w" . (1 [:p :q] ( 2 ) ) .
Parent topic: Other Recommendations and Guidelines
7.15.4 Limit in the SERVICE Clause
When writing a SPARQL 1.1 federated query, you can set a limit on returned rows in the subquery inside the SERVICE clause. This can effectively constrain the amount of data to be transported between the local repository and the remote SPARQL endpoint.
For example, the following query specifies limit 100
in the subquery in the SERVICE clause:
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 } }
Parent topic: Other Recommendations and Guidelines
7.15.5 OracleGraphWrapperForOntModel Class for Better Performance
The Jena OntModel
class lets you create, modify, and analyze an
ontology stored in a Jena model. However, the OntModel
implementation
is not optimized for RDF data stored in a database. This results in suboptimal
performance when using OntModel
with an Oracle model. Therefore, the
class OracleGraphWrapperForOntModel
has been created to alleviate this
performance issue.
The OracleGraphWrapperForOntModel
class implements the Jena
Graph
interface and represents a graph backed by an Oracle RDF/OWL
graph that is meant for use with the Jena OntModel
API. The
OracleGraphWrapperForOntModel
class uses two RDF stores in a hybrid
approach for persisting changes and responding to queries. Both RDF stores contain the
same data, but one resides in memory while the other resides in the Oracle database.
When queried through OntModel
, the OracleGraphWrapperForOntModel
graph runs the queries against the in-memory store to improve performance. However, the OracleGraphWrapperForOntModel
class persists changes made through OntModel
, such as adding or removing classes, by applying changes to both stores.
Due to its hybrid approach, an OracleGraphWrapperForOntModel
graph requires that sufficient memory be allocated to the JVM to store a copy of the ontology in memory. In internal experiments, it was found that an ontology with approximately 3 million triples requires 6 or more GB of physical memory.
Example 7-15 Using OntModel with Ontology Stored in Oracle Database
Example 7-15 shows how to use the OntModel
APIs with an existing ontology stored in an Oracle model.
// 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();
Note that any OntModel
object created using
OracleGraphWrapperForOntModel
will not reflect changes made to
the underlying Oracle model by another process, through a separate
OntModel
, or through a separate Oracle graph referencing the
same underlying model. All changes to an ontology should go through a single
OntModel
object and its underlying
OracleGraphWrapperForOntModel
graph until the graph have been
closed.
Example 7-16 Using a Custom In-Memory Graph
If the default in-memory RDF store used by
OracleGraphWrapperForOntModel
is not sufficient for an ontology
and system, the class provides an interface for specifying a custom graph to use as
the in-memory store. Example 7-16 shows how to create an
OracleGraphWrapperForOntModel
that uses a custom in-memory
graph to answer queries from OntModel
.
// 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();
Parent topic: Other Recommendations and Guidelines