> ## Documentation Index
> Fetch the complete documentation index at: https://docs.turingdb.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Technical Report

# 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.

***

## Results Overview

### Poledb

| Query                                                                                                              | TuringDB | Neo4j  | Memgraph | Speedup vs Neo4j | Speedup vs Memgraph |
| ------------------------------------------------------------------------------------------------------------------ | -------- | ------ | -------- | ---------------- | ------------------- |
| `MATCH (n) RETURN n`                                                                                               | 57ms     | 3130ms | 1858ms   | 55x              | 33x                 |
| `MATCH (p:Person) RETURN p`                                                                                        | 3ms      | 134ms  | 25ms     | 45x              | 8.3x                |
| `MATCH (p:Person) RETURN count(p)`                                                                                 | 1ms      | 115ms  | 8ms      | 115x             | 8.0x                |
| `MATCH (c:Crime) RETURN c`                                                                                         | 15ms     | 842ms  | 772ms    | 56x              | 51x                 |
| `MATCH (c:Crime) RETURN count(c)`                                                                                  | 1ms      | 45ms   | 13ms     | 45x              | 13x                 |
| `MATCH ()-[r]->() RETURN r`                                                                                        | 64ms     | 2660ms | 2386ms   | 42x              | 37x                 |
| `MATCH ()-[r]->() RETURN count(r)`                                                                                 | 9ms      | 55ms   | 28ms     | 6.1x             | 3.1x                |
| `MATCH (p:Person {name: 'John'})-[:PARTY_TO]->(c:Crime) RETURN p, c`                                               | 4ms      | 24ms   | 0ms      | 6.0x             | -                   |
| `MATCH (p:Person)-[:PARTY_TO]->(c:Crime) RETURN p.name, p.surname, c.type`                                         | 1ms      | 28ms   | 11ms     | 28x              | 11x                 |
| `MATCH (p:Person {surname: 'Smith'})-[r]->(n) RETURN p`                                                            | 3ms      | 64ms   | 2ms      | 21x              | 0.7x                |
| `MATCH (p:Person)-[r]->(n) WHERE p.surname = 'Smith' RETURN p`                                                     | 3ms      | 60ms   | 1ms      | 20x              | 0.3x                |
| `MATCH (p1:Person)-[:PARTY_TO]->(c:Crime)<-[:PARTY_TO]-(p2:Person) WHERE p1 <> p2 RETURN p1.name, p2.name, c.type` | 1ms      | 126ms  | 8ms      | 126x             | 8.0x                |
| `MATCH (p1:Person)-[:KNOWS]->(p2:Person)-[:PARTY_TO]->(c:Crime) RETURN p1.name, p2.name`                           | 1ms      | 24ms   | 11ms     | 24x              | 11x                 |
| `MATCH (c:Crime)-[:OCCURRED_AT]->(l:Location) RETURN l.postcode`                                                   | 30ms     | 553ms  | 362ms    | 18x              | 12x                 |

### Reactome

| Query                                                                                                       | TuringDB | Neo4j   | Memgraph | Speedup vs Neo4j | Speedup vs Memgraph |
| ----------------------------------------------------------------------------------------------------------- | -------- | ------- | -------- | ---------------- | ------------------- |
| `MATCH (n:Drug) RETURN n`                                                                                   | 2ms      | 977ms   | 371ms    | 488x             | 186x                |
| `MATCH (n:ProteinDrug) RETURN n`                                                                            | 1ms      | 221ms   | 340ms    | 221x             | 340x                |
| `MATCH (n:Drug:ProteinDrug) RETURN n`                                                                       | 1ms      | 270ms   | 359ms    | 270x             | 359x                |
| `MATCH (n:Taxon)-->(m:Species) RETURN n,m`                                                                  | 1ms      | 259ms   | 301ms    | 259x             | 301x                |
| `MATCH (n)-->(m:Interaction)-->(o) RETURN n,m,o`                                                            | 707ms    | 33117ms | 32609ms  | 47x              | 46x                 |
| `MATCH (n{displayName:"Autophagy"}) RETURN n`                                                               | 283ms    | 918ms   | 629ms    | 3.2x             | 2.2x                |
| `MATCH (n{displayName:"Autophagy"})-->(m) RETURN m`                                                         | 216ms    | 628ms   | 540ms    | 2.9x             | 2.5x                |
| `MATCH (n{displayName:"Autophagy"})-->(m)-->(p) RETURN p`                                                   | 215ms    | 622ms   | 569ms    | 2.9x             | 2.6x                |
| `MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q) RETURN q`                                             | 370ms    | 878ms   | 702ms    | 2.4x             | 1.9x                |
| `MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r) RETURN r`                                       | 236ms    | 2776ms  | 2595ms   | 12x              | 11x                 |
| `MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s) RETURN s`                                 | 296ms    | 5784ms  | 5012ms   | 20x              | 17x                 |
| `MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t) RETURN t`                           | 493ms    | 17983ms | 17256ms  | 36x              | 35x                 |
| `MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t)-->(v) RETURN v`                     | 1149ms   | 66876ms | 54252ms  | 58x              | 47x                 |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"}) RETURN n`                                           | 351ms    | 887ms   | 705ms    | 2.5x             | 2.0x                |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m) RETURN m`                                     | 215ms    | 734ms   | 567ms    | 3.4x             | 2.6x                |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p) RETURN p`                               | 211ms    | 616ms   | 603ms    | 2.9x             | 2.9x                |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q) RETURN q`                         | 213ms    | 613ms   | 585ms    | 2.9x             | 2.7x                |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r) RETURN r`                   | 213ms    | 649ms   | 560ms    | 3.0x             | 2.6x                |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s) RETURN s`             | 211ms    | 669ms   | 537ms    | 3.2x             | 2.5x                |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t) RETURN t`       | 211ms    | 644ms   | 557ms    | 3.1x             | 2.6x                |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t)-->(v) RETURN v` | 215ms    | 11087ms | 465ms    | 52x              | 2.2x                |
| `MATCH (n)-[e:release]->(m) RETURN n,m`                                                                     | 240ms    | 4046ms  | 3162ms   | 17x              | 13x                 |
| `MATCH (n)-[e:interactor]->(m) RETURN n,m`                                                                  | 318ms    | 26174ms | 25184ms  | 82x              | 79x                 |
| `MATCH (n)-[e:surroundedBy]->(m) RETURN n,m`                                                                | 202ms    | 1548ms  | 367ms    | 7.7x             | 1.8x                |
| `MATCH (n)-[:hasEvent]->(m) RETURN n,m`                                                                     | 292ms    | 11204ms | 11008ms  | 38x              | 38x                 |
| `MATCH (n:Pathway)-[:hasEvent]->(m:ReactionLikeEvent) RETURN n,m`                                           | 94ms     | 8442ms  | 8696ms   | 90x              | 93x                 |
| `MATCH (r:ReactionLikeEvent)-[:output]->(s:PhysicalEntity) RETURN r,s`                                      | 184ms    | 13383ms | 13591ms  | 73x              | 74x                 |
| `MATCH (n:DatabaseObject{isChimeric:false}) RETURN n`                                                       | 239ms    | 2507ms  | 1538ms   | 10x              | 6.4x                |
| `MATCH (n:DatabaseObject{isChimeric:true}) RETURN n`                                                        | 213ms    | 799ms   | 429ms    | 3.8x             | 2.0x                |
| `MATCH (b)-->(a:Pathway) RETURN a`                                                                          | 324ms    | 4447ms  | 5917ms   | 14x              | 18x                 |
| `MATCH (c)-->(b)-->(a:Pathway) RETURN a, c`                                                                 | 2318ms   | 35138ms | 34946ms  | 15x              | 15x                 |
| `MATCH (c)-->(b)-->(a:Pathway) RETURN b`                                                                    | 2109ms   | 22699ms | 22932ms  | 11x              | 11x                 |
| `MATCH (c)-->(b)-->(a:Pathway) RETURN c`                                                                    | 1978ms   | 18090ms | 17969ms  | 9.1x             | 9.1x                |
| `MATCH (c)-->(b)-->(a:Pathway) RETURN a`                                                                    | 1977ms   | 22424ms | 23598ms  | 11x              | 12x                 |

***

## Test Environment

### Hardware

| Spec    | Value                       |
| ------- | --------------------------- |
| CPU     | Intel(R) Xeon(R) Gold 5412U |
| Cores   | 48                          |
| RAM     | 256G                        |
| Storage | SSD                         |
| OS      | Ubuntu 24.04.3 LTS          |

### Software Versions

**Database Engines**

| Database | Version          |
| -------- | ---------------- |
| TuringDB | 1.0              |
| Neo4j    | 5.26.19-SNAPSHOT |
| Memgraph | unknown          |

**Client & Tools**

| Component             | Version |
| --------------------- | ------- |
| Python                | 3.13.11 |
| turingdb (Python SDK) | 1.20.0  |
| neo4j (Python driver) | 6.1.0   |
| mgconsole             | 1.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.

***

## 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](https://github.com/turing-db/turing-bench) for reproduction steps). The data is identical across all three databases.

### Poledb

| Metric             | Count   |
| ------------------ | ------- |
| Nodes              | 61,521  |
| Relationships      | 105,840 |
| Node Labels        | 11      |
| Relationship Types | 17      |
| Benchmark Queries  | 14      |

**Node Labels**

| Label     | Count  |
| --------- | ------ |
| Crime     | 28,762 |
| Location  | 14,904 |
| PostCode  | 14,196 |
| Officer   | 1,000  |
| Vehicle   | 1,000  |
| PhoneCall | 534    |
| Person    | 369    |
| Phone     | 328    |
| Email     | 328    |
| Area      | 93     |
| Object    | 7      |

**Relationship Types**

| Type               | Count  |
| ------------------ | ------ |
| OCCURRED\_AT       | 28,762 |
| INVESTIGATED\_BY   | 28,762 |
| HAS\_POSTCODE      | 14,904 |
| LOCATION\_IN\_AREA | 14,904 |
| POSTCODE\_IN\_AREA | 14,196 |
| INVOLVED\_IN       | 985    |
| KNOWS              | 586    |
| CALLER             | 534    |
| CALLED             | 534    |
| CURRENT\_ADDRESS   | 368    |
| HAS\_PHONE         | 328    |
| HAS\_EMAIL         | 328    |
| KNOWS\_SN          | 241    |
| FAMILY\_REL        | 155    |
| KNOWS\_PHONE       | 118    |
| KNOWS\_LW          | 80     |
| PARTY\_TO          | 55     |

### Reactome

| Metric             | Count      |
| ------------------ | ---------- |
| Nodes              | 2,978,202  |
| Relationships      | 11,537,843 |
| Node Labels        | 108        |
| Relationship Types | 88         |
| Benchmark Queries  | 34         |

**Node Labels**

| Label                            | Count     |
| -------------------------------- | --------- |
| DatabaseObject                   | 2,978,202 |
| ReferenceEntity                  | 930,514   |
| ReferenceSequence                | 927,102   |
| DatabaseIdentifier               | 856,680   |
| ReferenceDNASequence             | 617,302   |
| Deletable                        | 532,391   |
| Trackable                        | 524,558   |
| PhysicalEntity                   | 406,613   |
| GenomeEncodedEntity              | 246,176   |
| EntityWithAccessionedSequence    | 238,918   |
| ReferenceRNASequence             | 204,186   |
| Person                           | 171,942   |
| InstanceEdit                     | 157,659   |
| Event                            | 117,945   |
| Complex                          | 110,048   |
| ReferenceGeneProduct             | 105,614   |
| ReactionLikeEvent                | 94,655    |
| Reaction                         | 83,459    |
| MetaDatabaseObject               | 79,220    |
| Interaction                      | 77,995    |
| UndirectedInteraction            | 77,995    |
| UpdateTracker                    | 60,837    |
| AbstractModifiedResidue          | 56,756    |
| TranslationalModification        | 50,733    |
| EntitySet                        | 43,526    |
| Publication                      | 42,286    |
| LiteratureReference              | 42,098    |
| CatalystActivity                 | 40,297    |
| ModifiedResidue                  | 36,547    |
| DefinedSet                       | 34,937    |
| Pathway                          | 23,290    |
| Summation                        | 21,332    |
| GroupModifiedResidue             | 13,057    |
| DeletedInstance                  | 10,573    |
| BlackBoxEvent                    | 10,435    |
| CandidateSet                     | 8,589     |
| Regulation                       | 7,833     |
| Deleted                          | 7,668     |
| GeneticallyModifiedResidue       | 5,947     |
| PositiveRegulation               | 4,590     |
| SimpleEntity                     | 3,897     |
| ReplacedResidue                  | 3,459     |
| ControlReference                 | 3,367     |
| NegativeRegulation               | 3,243     |
| GO\_Term                         | 3,198     |
| FragmentModification             | 2,488     |
| ReferenceIsoform                 | 2,369     |
| FragmentReplacedModification     | 2,259     |
| ReferenceMolecule                | 2,183     |
| RegulationReference              | 1,897     |
| GO\_MolecularFunction            | 1,665     |
| Polymer                          | 1,391     |
| NonsenseMutation                 | 1,331     |
| PositiveGeneExpressionRegulation | 1,308     |
| Drug                             | 1,203     |
| CrosslinkedResidue               | 1,129     |
| ChemicalDrug                     | 1,106     |
| CatalystActivityReference        | 1,105     |
| ReferenceTherapeutic             | 1,087     |
| GO\_BiologicalProcess            | 1,082     |
| NegativePrecedingEvent           | 1,065     |
| ExternalOntology                 | 1,008     |
| Figure                           | 882       |
| Requirement                      | 851       |
| Disease                          | 770       |
| InterChainCrosslinkedResidue     | 747       |
| EntityFunctionalStatus           | 698       |
| FailedReaction                   | 457       |
| GO\_CellularComponent            | 451       |
| TopLevelPathway                  | 415       |
| Taxon                            | 408       |
| IntraChainCrosslinkedResidue     | 382       |
| MarkerReference                  | 365       |
| Affiliation                      | 348       |
| OtherEntity                      | 348       |
| NegativeGeneExpressionRegulation | 331       |
| Polymerisation                   | 253       |
| PsiMod                           | 175       |
| Compartment                      | 156       |
| FragmentInsertionModification    | 145       |
| ReferenceGroup                   | 142       |
| Release                          | 142       |
| Book                             | 133       |
| ReferenceDatabase                | 103       |
| Species                          | 95        |
| ProteinDrug                      | 95        |
| FragmentDeletionModification     | 84        |
| ModifiedNucleotide               | 76        |
| TranscriptionalModification      | 76        |
| URL                              | 55        |
| CellType                         | 31        |
| Depolymerisation                 | 29        |
| FunctionalStatus                 | 27        |
| Cell                             | 24        |
| CellDevelopmentStep              | 22        |
| ControlledVocabulary             | 21        |
| SequenceOntology                 | 15        |
| Anatomy                          | 14        |
| CellLineagePath                  | 12        |
| DeletedControlledVocabulary      | 7         |
| NegativePrecedingEventReason     | 6         |
| ReviewStatus                     | 5         |
| FunctionalStatusType             | 5         |
| EvidenceType                     | 3         |
| DrugActionType                   | 3         |
| ReactionType                     | 3         |
| RNADrug                          | 2         |
| DBInfo                           | 1         |

**Relationship Types**

| Type                      | Count     |
| ------------------------- | --------- |
| created                   | 2,797,487 |
| referenceDatabase         | 1,869,394 |
| crossReference            | 1,094,497 |
| species                   | 739,423   |
| referenceGene             | 639,701   |
| compartment               | 560,432   |
| inferredTo                | 455,759   |
| author                    | 422,897   |
| hasComponent              | 274,487   |
| referenceEntity           | 244,018   |
| referenceTranscript       | 219,870   |
| summation                 | 210,761   |
| input                     | 186,017   |
| hasMember                 | 172,620   |
| modified                  | 165,988   |
| output                    | 158,432   |
| interactor                | 155,990   |
| hasModifiedResidue        | 124,194   |
| hasEvent                  | 120,933   |
| literatureReference       | 106,182   |
| evidenceType              | 96,169    |
| precedingEvent            | 73,882    |
| release                   | 60,837    |
| updatedInstance           | 60,837    |
| referenceSequence         | 56,756    |
| psiMod                    | 56,312    |
| catalystActivity          | 52,010    |
| activity                  | 40,699    |
| physicalEntity            | 40,297    |
| hasCandidate              | 35,687    |
| reviewed                  | 27,812    |
| authored                  | 23,491    |
| reviewStatus              | 21,779    |
| edited                    | 21,549    |
| disease                   | 20,493    |
| goBiologicalProcess       | 18,300    |
| modification              | 14,050    |
| activeUnit                | 11,790    |
| regulatedBy               | 11,164    |
| deletedInstance           | 10,591    |
| regulator                 | 7,833     |
| reason                    | 7,099     |
| includedLocation          | 6,960     |
| hasEncapsulatedEvent      | 6,524     |
| replacementInstances      | 3,967     |
| relatedSpecies            | 3,030     |
| structureModified         | 2,943     |
| internalReviewed          | 2,675     |
| regulationReference       | 1,985     |
| regulation                | 1,897     |
| previousReviewStatus      | 1,795     |
| repeatedUnit              | 1,432     |
| revised                   | 1,423     |
| catalystActivityReference | 1,402     |
| negativePrecedingEvent    | 1,065     |
| functionalStatus          | 1,061     |
| figure                    | 940       |
| entityFunctionalStatus    | 798       |
| secondReferenceSequence   | 747       |
| normalReaction            | 722       |
| diseaseEntity             | 698       |
| equivalentTo              | 683       |
| normalEntity              | 617       |
| goCellularComponent       | 612       |
| entityOnOtherCell         | 563       |
| instanceOf                | 535       |
| affiliation               | 494       |
| normalPathway             | 469       |
| superTaxon                | 404       |
| isoformParent             | 384       |
| marker                    | 365       |
| cell                      | 365       |
| markerReference           | 365       |
| componentOf               | 272       |
| proteinMarker             | 191       |
| surroundedBy              | 189       |
| RNAMarker                 | 172       |
| cellType                  | 114       |
| reverseReaction           | 112       |
| requiredInputComponent    | 105       |
| publisher                 | 97        |
| hasPart                   | 33        |
| tissue                    | 30        |
| functionalStatusType      | 27        |
| structuralVariant         | 27        |
| reactionType              | 15        |
| organ                     | 15        |
| tissueLayer               | 5         |

***

## 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

***

## Results by Query Category

### Label Scans

**Poledb:**

| Query                       | TuringDB | Neo4j | Memgraph | Speedup vs Neo4j | Speedup vs Memgraph |
| --------------------------- | -------- | ----- | -------- | ---------------- | ------------------- |
| `MATCH (p:Person) RETURN p` | 3ms      | 134ms | 25ms     | 45x              | 8.3x                |
| `MATCH (c:Crime) RETURN c`  | 15ms     | 842ms | 772ms    | 56x              | 51x                 |

**Reactome:**

| Query                                 | TuringDB | Neo4j | Memgraph | Speedup vs Neo4j | Speedup vs Memgraph |
| ------------------------------------- | -------- | ----- | -------- | ---------------- | ------------------- |
| `MATCH (n:Drug) RETURN n`             | 2ms      | 977ms | 371ms    | 488x             | 186x                |
| `MATCH (n:ProteinDrug) RETURN n`      | 1ms      | 221ms | 340ms    | 221x             | 340x                |
| `MATCH (n:Drug:ProteinDrug) RETURN n` | 1ms      | 270ms | 359ms    | 270x             | 359x                |

### Full Graph Scans

**Poledb:**

| Query                       | TuringDB | Neo4j  | Memgraph | Speedup vs Neo4j | Speedup vs Memgraph |
| --------------------------- | -------- | ------ | -------- | ---------------- | ------------------- |
| `MATCH (n) RETURN n`        | 57ms     | 3130ms | 1858ms   | 55x              | 33x                 |
| `MATCH ()-[r]->() RETURN r` | 64ms     | 2660ms | 2386ms   | 42x              | 37x                 |

### Property-Based Filtering

**Poledb:**

| Query                                                                                                              | TuringDB | Neo4j | Memgraph | Speedup vs Neo4j | Speedup vs Memgraph |
| ------------------------------------------------------------------------------------------------------------------ | -------- | ----- | -------- | ---------------- | ------------------- |
| `MATCH (p:Person {name: 'John'})-[:PARTY_TO]->(c:Crime) RETURN p, c`                                               | 4ms      | 24ms  | 0ms      | 6.0x             | -                   |
| `MATCH (p:Person {surname: 'Smith'})-[r]->(n) RETURN p`                                                            | 3ms      | 64ms  | 2ms      | 21x              | 0.7x                |
| `MATCH (p:Person)-[r]->(n) WHERE p.surname = 'Smith' RETURN p`                                                     | 3ms      | 60ms  | 1ms      | 20x              | 0.3x                |
| `MATCH (p1:Person)-[:PARTY_TO]->(c:Crime)<-[:PARTY_TO]-(p2:Person) WHERE p1 <> p2 RETURN p1.name, p2.name, c.type` | 1ms      | 126ms | 8ms      | 126x             | 8.0x                |

**Reactome:**

| Query                                                                   | TuringDB | Neo4j  | Memgraph | Speedup vs Neo4j | Speedup vs Memgraph |
| ----------------------------------------------------------------------- | -------- | ------ | -------- | ---------------- | ------------------- |
| `MATCH (n{displayName:"Autophagy"}) RETURN n`                           | 283ms    | 918ms  | 629ms    | 3.2x             | 2.2x                |
| `MATCH (n{displayName:"Autophagy"})-->(m) RETURN m`                     | 216ms    | 628ms  | 540ms    | 2.9x             | 2.5x                |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"}) RETURN n`       | 351ms    | 887ms  | 705ms    | 2.5x             | 2.0x                |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m) RETURN m` | 215ms    | 734ms  | 567ms    | 3.4x             | 2.6x                |
| `MATCH (n:DatabaseObject{isChimeric:false}) RETURN n`                   | 239ms    | 2507ms | 1538ms   | 10x              | 6.4x                |
| `MATCH (n:DatabaseObject{isChimeric:true}) RETURN n`                    | 213ms    | 799ms  | 429ms    | 3.8x             | 2.0x                |

### Relationship Type Traversal

**Poledb:**

| Query                                                                                    | TuringDB | Neo4j | Memgraph | Speedup vs Neo4j | Speedup vs Memgraph |
| ---------------------------------------------------------------------------------------- | -------- | ----- | -------- | ---------------- | ------------------- |
| `MATCH (p:Person)-[:PARTY_TO]->(c:Crime) RETURN p.name, p.surname, c.type`               | 1ms      | 28ms  | 11ms     | 28x              | 11x                 |
| `MATCH (p1:Person)-[:KNOWS]->(p2:Person)-[:PARTY_TO]->(c:Crime) RETURN p1.name, p2.name` | 1ms      | 24ms  | 11ms     | 24x              | 11x                 |
| `MATCH (c:Crime)-[:OCCURRED_AT]->(l:Location) RETURN l.postcode`                         | 30ms     | 553ms | 362ms    | 18x              | 12x                 |

**Reactome:**

| Query                                                                  | TuringDB | Neo4j   | Memgraph | Speedup vs Neo4j | Speedup vs Memgraph |
| ---------------------------------------------------------------------- | -------- | ------- | -------- | ---------------- | ------------------- |
| `MATCH (n)-[e:release]->(m) RETURN n,m`                                | 240ms    | 4046ms  | 3162ms   | 17x              | 13x                 |
| `MATCH (n)-[e:interactor]->(m) RETURN n,m`                             | 318ms    | 26174ms | 25184ms  | 82x              | 79x                 |
| `MATCH (n)-[e:surroundedBy]->(m) RETURN n,m`                           | 202ms    | 1548ms  | 367ms    | 7.7x             | 1.8x                |
| `MATCH (n)-[:hasEvent]->(m) RETURN n,m`                                | 292ms    | 11204ms | 11008ms  | 38x              | 38x                 |
| `MATCH (n:Pathway)-[:hasEvent]->(m:ReactionLikeEvent) RETURN n,m`      | 94ms     | 8442ms  | 8696ms   | 90x              | 93x                 |
| `MATCH (r:ReactionLikeEvent)-[:output]->(s:PhysicalEntity) RETURN r,s` | 184ms    | 13383ms | 13591ms  | 73x              | 74x                 |

### Multi-Hop Traversals

**Reactome:**

| Query                                                                                                       | TuringDB | Neo4j   | Memgraph | Speedup vs Neo4j | Speedup vs Memgraph |
| ----------------------------------------------------------------------------------------------------------- | -------- | ------- | -------- | ---------------- | ------------------- |
| `MATCH (n{displayName:"Autophagy"})-->(m)-->(p) RETURN p`                                                   | 215ms    | 622ms   | 569ms    | 2.9x             | 2.6x                |
| `MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q) RETURN q`                                             | 370ms    | 878ms   | 702ms    | 2.4x             | 1.9x                |
| `MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r) RETURN r`                                       | 236ms    | 2776ms  | 2595ms   | 12x              | 11x                 |
| `MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s) RETURN s`                                 | 296ms    | 5784ms  | 5012ms   | 20x              | 17x                 |
| `MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t) RETURN t`                           | 493ms    | 17983ms | 17256ms  | 36x              | 35x                 |
| `MATCH (n{displayName:"Autophagy"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t)-->(v) RETURN v`                     | 1149ms   | 66876ms | 54252ms  | 58x              | 47x                 |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p) RETURN p`                               | 211ms    | 616ms   | 603ms    | 2.9x             | 2.9x                |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q) RETURN q`                         | 213ms    | 613ms   | 585ms    | 2.9x             | 2.7x                |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r) RETURN r`                   | 213ms    | 649ms   | 560ms    | 3.0x             | 2.6x                |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s) RETURN s`             | 211ms    | 669ms   | 537ms    | 3.2x             | 2.5x                |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t) RETURN t`       | 211ms    | 644ms   | 557ms    | 3.1x             | 2.6x                |
| `MATCH (n{displayName:"APOE-4 [extracellular region]"})-->(m)-->(p)-->(q)-->(r)-->(s)-->(t)-->(v) RETURN v` | 215ms    | 11087ms | 465ms    | 52x              | 2.2x                |

### Complex Patterns

**Reactome:**

| Query                                            | TuringDB | Neo4j   | Memgraph | Speedup vs Neo4j | Speedup vs Memgraph |
| ------------------------------------------------ | -------- | ------- | -------- | ---------------- | ------------------- |
| `MATCH (n:Taxon)-->(m:Species) RETURN n,m`       | 1ms      | 259ms   | 301ms    | 259x             | 301x                |
| `MATCH (n)-->(m:Interaction)-->(o) RETURN n,m,o` | 707ms    | 33117ms | 32609ms  | 47x              | 46x                 |
| `MATCH (b)-->(a:Pathway) RETURN a`               | 324ms    | 4447ms  | 5917ms   | 14x              | 18x                 |
| `MATCH (c)-->(b)-->(a:Pathway) RETURN a, c`      | 2318ms   | 35138ms | 34946ms  | 15x              | 15x                 |
| `MATCH (c)-->(b)-->(a:Pathway) RETURN b`         | 2109ms   | 22699ms | 22932ms  | 11x              | 11x                 |
| `MATCH (c)-->(b)-->(a:Pathway) RETURN c`         | 1978ms   | 18090ms | 17969ms  | 9.1x             | 9.1x                |
| `MATCH (c)-->(b)-->(a:Pathway) RETURN a`         | 1977ms   | 22424ms | 23598ms  | 11x              | 12x                 |

### Aggregations

**Poledb:**

| Query                              | TuringDB | Neo4j | Memgraph | Speedup vs Neo4j | Speedup vs Memgraph |
| ---------------------------------- | -------- | ----- | -------- | ---------------- | ------------------- |
| `MATCH (p:Person) RETURN count(p)` | 1ms      | 115ms | 8ms      | 115x             | 8.0x                |
| `MATCH (c:Crime) RETURN count(c)`  | 1ms      | 45ms  | 13ms     | 45x              | 13x                 |
| `MATCH ()-[r]->() RETURN count(r)` | 9ms      | 55ms  | 28ms     | 6.1x             | 3.1x                |

***

## 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.

***

## Where Competitors Win

The following **2 queries** (4% of benchmark) show a competitor outperforming TuringDB:

| Dataset | Query                                                          | Competitor | TuringDB | Competitor Time | Speedup |
| ------- | -------------------------------------------------------------- | ---------- | -------- | --------------- | ------- |
| poledb  | `MATCH (p:Person {surname: 'Smith'})-[r]->(n) RETURN p`        | Memgraph   | 3ms      | 2ms             | 0.7x    |
| poledb  | `MATCH (p:Person)-[r]->(n) WHERE p.surname = 'Smith' RETURN p` | Memgraph   | 3ms      | 1ms             | 0.3x    |

***

## 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.

***

## Reproducing the Benchmark

All benchmark code, queries, and dataset import scripts are open source:

**Repository:** [https://github.com/turing-db/turing-bench](https://github.com/turing-db/turing-bench)

```bash theme={null}
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](https://github.com/turing-db/turing-bench)
