One query, page by page, through a database built for ontologies
OntoDB stores RDF as 64-bit ids in B+ trees and answers SPARQL with a cost-based optimizer, a buffer pool and a write-ahead log. Everything below was printed by the real shell: its plans, its trees, every page the buffer pool fetched while it answered one LUBM query, and what it did after an abrupt exit.
Graduate students in GraduateCourse0, from SPARQL to rows
LUBM query 1 on one university, recorded with \trace on. Each step is one thing the engine did, in the order it did it, with the pages it pinned. Use the bar at the bottom, or the arrow keys.
Plan
Buffer pool
The store's pages
Detail
What the optimizer chose for each LUBM query
The fourteen LUBM queries under \explain analyze on the same university: each operator with the rows the optimizer estimated and the rows it produced. OntoDB does not do RDFS inference yet, so queries that rely on the class hierarchy return no rows here; LUBM's own note for each query says what it assumes.
A database directory survives an abrupt exit
ontodb mydb runs each statement as a transaction and forces its log records to mydb/wal before the prompt returns. \checkpoint writes a snapshot and resets the log. Here the shell exits with \crash, which flushes nothing, and the last 10 bytes of the log are cut off by hand to stand in for a write the disk never finished.
On disk
The two files in mydb/, to scale.
Log records
Everything under a class is a range scan
On a slice of the Gene Ontology, \hindex build numbers the class hierarchy so that each class owns a few integer intervals, kept in a B+ tree. "Every class at or below C" becomes one range scan per interval. The same intervals can restrict a vector search to the classes under C.
OntoDB against Oxigraph, Jena and SQLite
LUBM(10), query latency
Mean time per query, log scale; lower is better. 1.3 million triples. Queries that return no rows rely on inference that none of these runs did.
Show the table
Instances of a class and its subclasses
Gene Ontology, 200,000 entities; 30 classes per bucket of descendant count. OntoDB as ids (the ring) and as strings, which is what the others return.
Show the table
Lookups per second, by threads
The (s,.,.) and (s,p,.) lookups on LUBM(10), 3 seconds per cell. The machine has 8 performance cores.
Show the table
Loading LUBM(10)
OntoDB is the slowest to load and the second largest in memory: it builds three B+ trees and the dictionary from one pass over the file.