Skip to main content

TuringDB Benchmark Report

Date: 2026-02-16 Author(s): TuringDB team

Executive Summary

TuringDB is a column-oriented, in-memory graph database engine designed for analytical and read-intensive workloads. This report presents benchmark results comparing TuringDB against Neo4j and Memgraph across multiple datasets and query categories. What We Tested Poledb (~61K nodes / 105K relationships) Reactome (~3M nodes / 11.5M relationships) 48 real-world Cypher queries Cold runs only (no caching). No indexes, no database tuning. Same hardware, same machine. Headline Numbers Across all queries: 51.8× faster than Neo4j on average Median: 19× Max: 488× 41.3× faster than Memgraph on average Median 11x Max 359x Won 48/48 queries vs Neo4j Won 45/47 queries vs Memgraph And remember: All of this is running over plain JSON/HTTP for now, while competitors used Bolt (binary protocol), which actually makes the benchmark conservative in our case. We’re also running completely out-of-the-box with no manual tuning, no custom configuration, no indexes on our side. So we’re actually not giving ourselves any unfair advantage here.

1. Test Environment

Hardware

SpecValue
CPUIntel(R) Xeon(R) Gold 5412U
Cores48
RAM256G
StorageSSD
OSUbuntu 24.04.3 LTS

Software Versions

Database Engines
DatabaseVersion
TuringDB1.0
Neo4j5.26.19-SNAPSHOT
Memgraphunknown
Client & Tools
ComponentVersion
Python3.13.11
turingdb (Python SDK)1.20.0
neo4j (Python driver)6.1.0
mgconsole1.4
All databases were run locally on the same machine, one at a time, to avoid resource contention. Neo4j and Memgraph were imported with their native indexes and constraints from the original dump. Memgraph was run in in-memory analytical mode (--storage-mode=IN_MEMORY_ANALYTICAL). No additional engine-specific tuning was applied beyond what the import pipeline provides.

Client Protocol

TuringDB is queried over HTTP via its Python client, while Neo4j and Memgraph are queried over the Bolt binary protocol. Bolt is a more efficient wire protocol than HTTP for database communication, meaning TuringDB’s measured times include higher protocol overhead. This makes the benchmark conservative in TuringDB’s favor — with an equivalent binary protocol, TuringDB’s results would be even faster.

2. Dataset

This section describes the datasets used in the benchmark. Each dataset was imported into all three engines using the same pipeline (see turing-bench for reproduction steps). The data is identical across all three databases.

Poledb

MetricCount
Nodes61,521
Relationships105,840
Node Labels11
Relationship Types17
Benchmark Queries14
Node Labels
LabelCount
Crime28,762
Location14,904
PostCode14,196
Officer1,000
Vehicle1,000
PhoneCall534
Person369
Phone328
Email328
Area93
Object7
Relationship Types
TypeCount
OCCURRED_AT28,762
INVESTIGATED_BY28,762
HAS_POSTCODE14,904
LOCATION_IN_AREA14,904
POSTCODE_IN_AREA14,196
INVOLVED_IN985
KNOWS586
CALLER534
CALLED534
CURRENT_ADDRESS368
HAS_PHONE328
HAS_EMAIL328
KNOWS_SN241
FAMILY_REL155
KNOWS_PHONE118
KNOWS_LW80
PARTY_TO55

Reactome

MetricCount
Nodes2,978,202
Relationships11,537,843
Node Labels108
Relationship Types88
Benchmark Queries34
Node Labels
LabelCount
DatabaseObject2,978,202
ReferenceEntity930,514
ReferenceSequence927,102
DatabaseIdentifier856,680
ReferenceDNASequence617,302
Deletable532,391
Trackable524,558
PhysicalEntity406,613
GenomeEncodedEntity246,176
EntityWithAccessionedSequence238,918
ReferenceRNASequence204,186
Person171,942
InstanceEdit157,659
Event117,945
Complex110,048
ReferenceGeneProduct105,614
ReactionLikeEvent94,655
Reaction83,459
MetaDatabaseObject79,220
Interaction77,995
UndirectedInteraction77,995
UpdateTracker60,837
AbstractModifiedResidue56,756
TranslationalModification50,733
EntitySet43,526
Publication42,286
LiteratureReference42,098
CatalystActivity40,297
ModifiedResidue36,547
DefinedSet34,937
Pathway23,290
Summation21,332
GroupModifiedResidue13,057
DeletedInstance10,573
BlackBoxEvent10,435
CandidateSet8,589
Regulation7,833
Deleted7,668
GeneticallyModifiedResidue5,947
PositiveRegulation4,590
SimpleEntity3,897
ReplacedResidue3,459
ControlReference3,367
NegativeRegulation3,243
GO_Term3,198
FragmentModification2,488
ReferenceIsoform2,369
FragmentReplacedModification2,259
ReferenceMolecule2,183
RegulationReference1,897
GO_MolecularFunction1,665
Polymer1,391
NonsenseMutation1,331
PositiveGeneExpressionRegulation1,308
Drug1,203
CrosslinkedResidue1,129
ChemicalDrug1,106
CatalystActivityReference1,105
ReferenceTherapeutic1,087
GO_BiologicalProcess1,082
NegativePrecedingEvent1,065
ExternalOntology1,008
Figure882
Requirement851
Disease770
InterChainCrosslinkedResidue747
EntityFunctionalStatus698
FailedReaction457
GO_CellularComponent451
TopLevelPathway415
Taxon408
IntraChainCrosslinkedResidue382
MarkerReference365
Affiliation348
OtherEntity348
NegativeGeneExpressionRegulation331
Polymerisation253
PsiMod175
Compartment156
FragmentInsertionModification145
ReferenceGroup142
Release142
Book133
ReferenceDatabase103
Species95
ProteinDrug95
FragmentDeletionModification84
ModifiedNucleotide76
TranscriptionalModification76
URL55
CellType31
Depolymerisation29
FunctionalStatus27
Cell24
CellDevelopmentStep22
ControlledVocabulary21
SequenceOntology15
Anatomy14
CellLineagePath12
DeletedControlledVocabulary7
NegativePrecedingEventReason6
ReviewStatus5
FunctionalStatusType5
EvidenceType3
DrugActionType3
ReactionType3
RNADrug2
DBInfo1
Relationship Types
TypeCount
created2,797,487
referenceDatabase1,869,394
crossReference1,094,497
species739,423
referenceGene639,701
compartment560,432
inferredTo455,759
author422,897
hasComponent274,487
referenceEntity244,018
referenceTranscript219,870
summation210,761
input186,017
hasMember172,620
modified165,988
output158,432
interactor155,990
hasModifiedResidue124,194
hasEvent120,933
literatureReference106,182
evidenceType96,169
precedingEvent73,882
release60,837
updatedInstance60,837
referenceSequence56,756
psiMod56,312
catalystActivity52,010
activity40,699
physicalEntity40,297
hasCandidate35,687
reviewed27,812
authored23,491
reviewStatus21,779
edited21,549
disease20,493
goBiologicalProcess18,300
modification14,050
activeUnit11,790
regulatedBy11,164
deletedInstance10,591
regulator7,833
reason7,099
includedLocation6,960
hasEncapsulatedEvent6,524
replacementInstances3,967
relatedSpecies3,030
structureModified2,943
internalReviewed2,675
regulationReference1,985
regulation1,897
previousReviewStatus1,795
repeatedUnit1,432
revised1,423
catalystActivityReference1,402
negativePrecedingEvent1,065
functionalStatus1,061
figure940
entityFunctionalStatus798
secondReferenceSequence747
normalReaction722
diseaseEntity698
equivalentTo683
normalEntity617
goCellularComponent612
entityOnOtherCell563
instanceOf535
affiliation494
normalPathway469
superTaxon404
isoformParent384
marker365
cell365
markerReference365
componentOf272
proteinMarker191
surroundedBy189
RNAMarker172
cellType114
reverseReaction112
requiredInputComponent105
publisher97
hasPart33
tissue30
functionalStatusType27
structuralVariant27
reactionType15
organ15
tissueLayer5

3. Methodology

Benchmark Design

  • Each query is executed once per engine (cold run, no prior caching)
  • Timing is measured with nanosecond precision (time.perf_counter_ns()) from the Python client side, including network round-trip
  • All engines use the same Cypher queries, with minor syntax adaptations where necessary
  • Results include the full query execution and result materialization time

Why Cold Runs

Neo4j and Memgraph employ aggressive query result caching. After a first execution, subsequent runs of the same query return cached results in near-zero time, which does not reflect real-world analytical workload patterns where queries vary. We therefore report single cold-run timings to measure actual query processing performance.

Execution Pipeline

For each dataset, the benchmark pipeline (run.sh):
  1. Stops all database engines
  2. Starts the first engine and loads the dataset
  3. Executes all queries sequentially, recording wall-clock time per query
  4. Stops the engine and repeats for the next engine
  5. Generates a summary report with speedup ratios

4. Results Overview

Poledb

QueryTuringDBNeo4jMemgraphSpeedup vs Neo4jSpeedup vs Memgraph
MATCH (n) RETURN n57ms3130ms1858ms55x33x
MATCH (p:Person) RETURN p3ms134ms25ms45x8.3x
MATCH (p:Person) RETURN count(p)1ms115ms8ms115x8.0x
MATCH (c:Crime) RETURN c15ms842ms772ms56x51x
MATCH (c:Crime) RETURN count(c)1ms45ms13ms45x13x
MATCH ()-[r]->() RETURN r64ms2660ms2386ms42x37x
MATCH ()-[r]->() RETURN count(r)9ms55ms28ms6.1x3.1x
MATCH (p:Person {name: 'John'})-[:PARTY_TO]->(c:Crime) RETURN p, c4ms24ms0ms6.0x-
MATCH (p:Person)-[:PARTY_TO]->(c:Crime) RETURN p.name, p.surname, c.type1ms28ms11ms28x11x
MATCH (p:Person {surname: 'Smith'})-[r]->(n) RETURN p3ms64ms2ms21x0.7x
MATCH (p:Person)-[r]->(n) WHERE p.surname = 'Smith' RETURN p3ms60ms1ms20x0.3x
MATCH (p1:Person)-[:PARTY_TO]->(c:Crime)<-[:PARTY_TO]-(p2:Person) WHERE p1 <> p2 RETURN p1.name, p2.name, c.type1ms126ms8ms126x8.0x
MATCH (p1:Person)-[:KNOWS]->(p2:Person)-[:PARTY_TO]->(c:Crime) RETURN p1.name, p2.name1ms24ms11ms24x11x
MATCH (c:Crime)-[:OCCURRED_AT]->(l:Location) RETURN l.postcode30ms553ms362ms18x12x

Reactome

QueryTuringDBNeo4jMemgraphSpeedup vs Neo4jSpeedup vs Memgraph
MATCH (n:Drug) RETURN n2ms977ms371ms488x186x
MATCH (n:ProteinDrug) RETURN n1ms221ms340ms221x340x
MATCH (n:Drug:ProteinDrug) RETURN n1ms270ms359ms270x359x
MATCH (n:Taxon)-->(m:Species) RETURN n,m1ms259ms301ms259x301x
MATCH (n)-->(m:Interaction)-->(o) RETURN n,m,o707ms33117ms32609ms47x46x
MATCH (n{displayName:"Autophagy"}) RETURN n283ms918ms629ms3.2x2.2x
MATCH (n{displayName:"Autophagy"})-->(m) RETURN m216ms628ms540ms2.9x2.5x
MATCH (n{displayName:"Autophagy"})-->(m)-->(p) RETURN p215ms622ms569ms2.9x2.6x
MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q) RETURN q370ms878ms702ms2.4x1.9x
MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r) RETURN r236ms2776ms2595ms12x11x
MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s) RETURN s296ms5784ms5012ms20x17x
MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t) RETURN t493ms17983ms17256ms36x35x
MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t)-->(v) RETURN v1149ms66876ms54252ms58x47x
MATCH (n{displayName:"APOE-4 [extracellular region]"}) RETURN n351ms887ms705ms2.5x2.0x
MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m) RETURN m215ms734ms567ms3.4x2.6x
MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p) RETURN p211ms616ms603ms2.9x2.9x
MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q) RETURN q213ms613ms585ms2.9x2.7x
MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r) RETURN r213ms649ms560ms3.0x2.6x
MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s) RETURN s211ms669ms537ms3.2x2.5x
MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t) RETURN t211ms644ms557ms3.1x2.6x
MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t)-->(v) RETURN v215ms11087ms465ms52x2.2x
MATCH (n)-[e:release]->(m) RETURN n,m240ms4046ms3162ms17x13x
MATCH (n)-[e:interactor]->(m) RETURN n,m318ms26174ms25184ms82x79x
MATCH (n)-[e:surroundedBy]->(m) RETURN n,m202ms1548ms367ms7.7x1.8x
MATCH (n)-[:hasEvent]->(m) RETURN n,m292ms11204ms11008ms38x38x
MATCH (n:Pathway)-[:hasEvent]->(m:ReactionLikeEvent) RETURN n,m94ms8442ms8696ms90x93x
MATCH (r:ReactionLikeEvent)-[:output]->(s:PhysicalEntity) RETURN r,s184ms13383ms13591ms73x74x
MATCH (n:DatabaseObject{isChimeric:false}) RETURN n239ms2507ms1538ms10x6.4x
MATCH (n:DatabaseObject{isChimeric:true}) RETURN n213ms799ms429ms3.8x2.0x
MATCH (b)-->(a:Pathway) RETURN a324ms4447ms5917ms14x18x
MATCH (c)-->(b)-->(a:Pathway) RETURN a, c2318ms35138ms34946ms15x15x
MATCH (c)-->(b)-->(a:Pathway) RETURN b2109ms22699ms22932ms11x11x
MATCH (c)-->(b)-->(a:Pathway) RETURN c1978ms18090ms17969ms9.1x9.1x
MATCH (c)-->(b)-->(a:Pathway) RETURN a1977ms22424ms23598ms11x12x

5. Results by Query Category

5.1 Label Scans

Poledb:
QueryTuringDBNeo4jMemgraphSpeedup vs Neo4jSpeedup vs Memgraph
MATCH (p:Person) RETURN p3ms134ms25ms45x8.3x
MATCH (c:Crime) RETURN c15ms842ms772ms56x51x
Reactome:
QueryTuringDBNeo4jMemgraphSpeedup vs Neo4jSpeedup vs Memgraph
MATCH (n:Drug) RETURN n2ms977ms371ms488x186x
MATCH (n:ProteinDrug) RETURN n1ms221ms340ms221x340x
MATCH (n:Drug:ProteinDrug) RETURN n1ms270ms359ms270x359x

5.2 Full Graph Scans

Poledb:
QueryTuringDBNeo4jMemgraphSpeedup vs Neo4jSpeedup vs Memgraph
MATCH (n) RETURN n57ms3130ms1858ms55x33x
MATCH ()-[r]->() RETURN r64ms2660ms2386ms42x37x

5.3 Property-Based Filtering

Poledb:
QueryTuringDBNeo4jMemgraphSpeedup vs Neo4jSpeedup vs Memgraph
MATCH (p:Person {name: 'John'})-[:PARTY_TO]->(c:Crime) RETURN p, c4ms24ms0ms6.0x-
MATCH (p:Person {surname: 'Smith'})-[r]->(n) RETURN p3ms64ms2ms21x0.7x
MATCH (p:Person)-[r]->(n) WHERE p.surname = 'Smith' RETURN p3ms60ms1ms20x0.3x
MATCH (p1:Person)-[:PARTY_TO]->(c:Crime)<-[:PARTY_TO]-(p2:Person) WHERE p1 <> p2 RETURN p1.name, p2.name, c.type1ms126ms8ms126x8.0x
Reactome:
QueryTuringDBNeo4jMemgraphSpeedup vs Neo4jSpeedup vs Memgraph
MATCH (n{displayName:"Autophagy"}) RETURN n283ms918ms629ms3.2x2.2x
MATCH (n{displayName:"Autophagy"})-->(m) RETURN m216ms628ms540ms2.9x2.5x
MATCH (n{displayName:"APOE-4 [extracellular region]"}) RETURN n351ms887ms705ms2.5x2.0x
MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m) RETURN m215ms734ms567ms3.4x2.6x
MATCH (n:DatabaseObject{isChimeric:false}) RETURN n239ms2507ms1538ms10x6.4x
MATCH (n:DatabaseObject{isChimeric:true}) RETURN n213ms799ms429ms3.8x2.0x

5.4 Relationship Type Traversal

Poledb:
QueryTuringDBNeo4jMemgraphSpeedup vs Neo4jSpeedup vs Memgraph
MATCH (p:Person)-[:PARTY_TO]->(c:Crime) RETURN p.name, p.surname, c.type1ms28ms11ms28x11x
MATCH (p1:Person)-[:KNOWS]->(p2:Person)-[:PARTY_TO]->(c:Crime) RETURN p1.name, p2.name1ms24ms11ms24x11x
MATCH (c:Crime)-[:OCCURRED_AT]->(l:Location) RETURN l.postcode30ms553ms362ms18x12x
Reactome:
QueryTuringDBNeo4jMemgraphSpeedup vs Neo4jSpeedup vs Memgraph
MATCH (n)-[e:release]->(m) RETURN n,m240ms4046ms3162ms17x13x
MATCH (n)-[e:interactor]->(m) RETURN n,m318ms26174ms25184ms82x79x
MATCH (n)-[e:surroundedBy]->(m) RETURN n,m202ms1548ms367ms7.7x1.8x
MATCH (n)-[:hasEvent]->(m) RETURN n,m292ms11204ms11008ms38x38x
MATCH (n:Pathway)-[:hasEvent]->(m:ReactionLikeEvent) RETURN n,m94ms8442ms8696ms90x93x
MATCH (r:ReactionLikeEvent)-[:output]->(s:PhysicalEntity) RETURN r,s184ms13383ms13591ms73x74x

5.5 Multi-Hop Traversals

Reactome:
QueryTuringDBNeo4jMemgraphSpeedup vs Neo4jSpeedup vs Memgraph
MATCH (n{displayName:"Autophagy"})-->(m)-->(p) RETURN p215ms622ms569ms2.9x2.6x
MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q) RETURN q370ms878ms702ms2.4x1.9x
MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r) RETURN r236ms2776ms2595ms12x11x
MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s) RETURN s296ms5784ms5012ms20x17x
MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t) RETURN t493ms17983ms17256ms36x35x
MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t)-->(v) RETURN v1149ms66876ms54252ms58x47x
MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p) RETURN p211ms616ms603ms2.9x2.9x
MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q) RETURN q213ms613ms585ms2.9x2.7x
MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r) RETURN r213ms649ms560ms3.0x2.6x
MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s) RETURN s211ms669ms537ms3.2x2.5x
MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t) RETURN t211ms644ms557ms3.1x2.6x
MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t)-->(v) RETURN v215ms11087ms465ms52x2.2x

5.6 Complex Patterns

Reactome:
QueryTuringDBNeo4jMemgraphSpeedup vs Neo4jSpeedup vs Memgraph
MATCH (n:Taxon)-->(m:Species) RETURN n,m1ms259ms301ms259x301x
MATCH (n)-->(m:Interaction)-->(o) RETURN n,m,o707ms33117ms32609ms47x46x
MATCH (b)-->(a:Pathway) RETURN a324ms4447ms5917ms14x18x
MATCH (c)-->(b)-->(a:Pathway) RETURN a, c2318ms35138ms34946ms15x15x
MATCH (c)-->(b)-->(a:Pathway) RETURN b2109ms22699ms22932ms11x11x
MATCH (c)-->(b)-->(a:Pathway) RETURN c1978ms18090ms17969ms9.1x9.1x
MATCH (c)-->(b)-->(a:Pathway) RETURN a1977ms22424ms23598ms11x12x

5.7 Aggregations

Poledb:
QueryTuringDBNeo4jMemgraphSpeedup vs Neo4jSpeedup vs Memgraph
MATCH (p:Person) RETURN count(p)1ms115ms8ms115x8.0x
MATCH (c:Crime) RETURN count(c)1ms45ms13ms45x13x
MATCH ()-[r]->() RETURN count(r)9ms55ms28ms6.1x3.1x

6. Why TuringDB Is Faster: Architectural Deep Dive

Column-Oriented Storage vs. Row-Oriented

Traditional graph databases (Neo4j, Memgraph) use row-oriented storage: each node is stored as a self-contained record with all its properties and adjacency pointers. This is efficient for single-node lookups but wasteful for analytical queries that scan many nodes and only need a few properties. TuringDB uses column-oriented storage: each property is stored as a separate, contiguous array. This design, proven in analytical relational databases (ClickHouse, DuckDB), is adapted here for graph workloads. Impact on benchmarks:
  • Label scans touch only the label column, not entire node records
  • Property filters scan a single column instead of deserializing full nodes
  • Aggregations (COUNT, etc.) operate on dense integer arrays

Streaming Execution vs. Volcano Model

Neo4j and Memgraph use the Volcano (iterator) model: each operator in the query plan produces one row at a time, pulling from the operator below. This introduces per-row function call overhead and prevents vectorized processing. TuringDB uses a streaming columnar execution engine: each operator processes a batch of values (a column) at once. This enables:
  • SIMD vectorization — processing multiple values per CPU instruction
  • Reduced function call overhead — one call per batch, not per row
  • Better branch prediction — uniform operations on homogeneous data

Zero-Locking Snapshot Isolation

TuringDB’s immutable DataPart architecture means read queries never contend with writes. While this benchmark runs queries sequentially (no concurrent load), the zero-locking design means there is no lock acquisition overhead even for single queries — the engine skips the entire lock management code path.

No Index Dependency

Neo4j and Memgraph rely on indexes to accelerate property lookups — and in this benchmark, they benefit from the indexes and constraints included in the original dataset dump. TuringDB does not use explicit index structures. Its columnar layout makes property scans inherently fast — the column itself acts as a natural “index” for scan-based access patterns. Despite the competitors having indexes available, TuringDB still outperforms them on most property filter queries.

7. Where Competitors Win

The following 2 queries (4% of benchmark) show a competitor outperforming TuringDB:
DatasetQueryCompetitorTuringDBCompetitor TimeSpeedup
poledbMATCH (p:Person {surname: 'Smith'})-[r]->(n) RETURN pMemgraph3ms2ms0.7x
poledbMATCH (p:Person)-[r]->(n) WHERE p.surname = 'Smith' RETURN pMemgraph3ms1ms0.3x

8. Limitations and Caveats

  • Single-machine benchmark. All engines ran locally; distributed deployment characteristics are not measured.
  • Cold-run only. Results reflect first-execution performance. Workloads with repeated identical queries would benefit from Neo4j/Memgraph’s query caching.
  • Import-provided configuration. Neo4j and Memgraph use the indexes and constraints from the original dump, and Memgraph runs in in-memory analytical mode. No additional tuning was applied. Production deployments may include further optimizations.
  • Client-side timing. Measurements include Python client overhead and network round-trip (localhost). TuringDB uses HTTP while Neo4j and Memgraph use the more efficient Bolt protocol, giving the competitors a wire-protocol advantage.
  • Two datasets. Results may not generalize to all graph structures or query patterns. Additional datasets would strengthen conclusions.
  • No concurrent load. The benchmark runs queries sequentially with no simulated concurrent users.

9. Reproducing the Benchmark

All benchmark code, queries, and dataset import scripts are open source: Repository: https://github.com/turing-db/turing-bench
git clone https://github.com/turing-db/turing-bench.git
cd turing-bench

# Install engines
./install.sh

# Set up environment
source env.sh

# Download and import dataset
./scripts/neo4j-43-imports/run_all.sh {dataset_name}

# Run full benchmark
./run.sh {dataset_name}
The benchmark script generates a timestamped report and optionally updates the README with a summary table.

Appendix A: Full Query Listing

  • Click to expand

    Poledb

    Full Graph Scans

    MATCH (n) RETURN n
    MATCH ()-[r]->() RETURN r
    

    Label Scans

    MATCH (p:Person) RETURN p
    MATCH (c:Crime) RETURN c
    

    Property-Based Filtering

    MATCH (p:Person {name: 'John'})-[:PARTY_TO]->(c:Crime) RETURN p, c
    MATCH (p:Person {surname: 'Smith'})-[r]->(n) RETURN p
    MATCH (p:Person)-[r]->(n) WHERE p.surname = 'Smith' RETURN p
    MATCH (p1:Person)-[:PARTY_TO]->(c:Crime)<-[:PARTY_TO]-(p2:Person) WHERE p1 <> p2 RETURN p1.name, p2.name, c.type
    

    Aggregations

    MATCH (p:Person) RETURN count(p)
    MATCH (c:Crime) RETURN count(c)
    MATCH ()-[r]->() RETURN count(r)
    

    Relationship Type Traversal

    MATCH (p:Person)-[:PARTY_TO]->(c:Crime) RETURN p.name, p.surname, c.type
    MATCH (p1:Person)-[:KNOWS]->(p2:Person)-[:PARTY_TO]->(c:Crime) RETURN p1.name, p2.name
    MATCH (c:Crime)-[:OCCURRED_AT]->(l:Location) RETURN l.postcode
    

    Reactome

    Label Scans

    MATCH (n:Drug) RETURN n
    MATCH (n:ProteinDrug) RETURN n
    MATCH (n:Drug:ProteinDrug) RETURN n
    

    Property-Based Filtering

    MATCH (n{displayName:"Autophagy"}) RETURN n
    MATCH (n{displayName:"Autophagy"})-->(m) RETURN m
    MATCH (n{displayName:"APOE-4 [extracellular region]"}) RETURN n
    MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m) RETURN m
    MATCH (n:DatabaseObject{isChimeric:false}) RETURN n
    MATCH (n:DatabaseObject{isChimeric:true}) RETURN n
    

    Multi-Hop Traversals

    MATCH (n{displayName:"Autophagy"})-->(m)-->(p) RETURN p
    MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q) RETURN q
    MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r) RETURN r
    MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s) RETURN s
    MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t) RETURN t
    MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t)-->(v) RETURN v
    MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p) RETURN p
    MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q) RETURN q
    MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r) RETURN r
    MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s) RETURN s
    MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t) RETURN t
    MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t)-->(v) RETURN v
    

    Relationship Type Traversal

    MATCH (n)-[e:release]->(m) RETURN n,m
    MATCH (n)-[e:interactor]->(m) RETURN n,m
    MATCH (n)-[e:surroundedBy]->(m) RETURN n,m
    MATCH (n)-[:hasEvent]->(m) RETURN n,m
    MATCH (n:Pathway)-[:hasEvent]->(m:ReactionLikeEvent) RETURN n,m
    MATCH (r:ReactionLikeEvent)-[:output]->(s:PhysicalEntity) RETURN r,s
    

    Complex Patterns

    MATCH (n:Taxon)-->(m:Species) RETURN n,m
    MATCH (n)-->(m:Interaction)-->(o) RETURN n,m,o
    MATCH (b)-->(a:Pathway) RETURN a
    MATCH (c)-->(b)-->(a:Pathway) RETURN a, c
    MATCH (c)-->(b)-->(a:Pathway) RETURN b
    MATCH (c)-->(b)-->(a:Pathway) RETURN c
    MATCH (c)-->(b)-->(a:Pathway) RETURN a
    

Appendix B: Raw Timing Data

The raw benchmark output (per-query mean/min/max/median) is available in the reports/ directory of the repository after running the benchmark. https://github.com/turing-db/turing-bench