Skip to main content

In this benchmark run

LoraDB is fastest overall across 82 workloads

Geometric-mean slowdown per engine across every workload they share. LoraDB wins eight of twelve groups; Grafeo takes setup and writes; Kuzu takes strings and numerics. Numbers here come straight from comparisons/report.md — same suite, same fixtures, same seed.

82 workloads12 groups6 comparison engines
LoraDB total
Fastest overall across this suite.
82
Workloads
12 groups · 6 engines compared
8/12
Groups won by LoraDB
Grafeo wins 2; Kuzu wins 2.
2.30×
vs. next-best total
Next-best (Grafeo) 2.30× slower overall.

Where LoraDB leads

Strongest across scans, predicates, traversals, and patterns.

LoraDB wins the group on every workload it touches in these areas. Strings and numerics belong to Kuzu (LoraDB is within ~22% on both); writes and setup belong to Grafeo (LoraDB pays roughly 2× on writes against Grafeo’s purpose-built crate path).

  • scans6 workloads
  • predicates12 workloads
  • aggregates9 workloads
  • pipeline9 workloads
  • lists3 workloads
  • sort3 workloads
  • traversals15 workloads
  • patterns4 workloads

Overall ranking

Total geometric-mean slowdown, ordered fastest to slowest.

Log scale. Bar length reflects log₁₀(slowdown) so multiples spanning 2.3×–57× remain visually comparable. Slowdowns are copied verbatim from comparisons/report.md.

Per group

Twelve groups, eighty-two workloads.

Each card shows the workload count, the group winner, and the per-engine slowdown chip. LoraDB sits in its own row so the comparison stays anchored even when LoraDB is not the row winner.

setup
1 workload
WinnerGrafeo
LoraDB2.70× slower
  • Kuzu700×
  • Grafeofastest
  • SurrealDBn/a
  • Memgraph904×
  • Neo4j1769×
  • HelixDB1247×
writes
9 workloads
WinnerGrafeo
LoraDB0.61× slower
  • Kuzu1.79×
  • Grafeofastest
  • SurrealDB28.3×
  • Memgraph3.71×
  • Neo4j7.75×
  • HelixDB125×
scans
6 workloads
WinnerLoraDB
LoraDBfastest
  • Kuzu6.37×
  • Grafeo5.43×
  • SurrealDB121×
  • Memgraph27.5×
  • Neo4j24.1×
  • HelixDB287×
predicates
12 workloads
WinnerLoraDB
LoraDBfastest
  • Kuzu1.14×
  • Grafeo1.83×
  • SurrealDB21.3×
  • Memgraph4.77×
  • Neo4j3.78×
  • HelixDB20.9×
strings
5 workloads
WinnerKuzu
LoraDB1.22× slower
  • Kuzufastest
  • Grafeo1.84×
  • SurrealDB34.1×
  • Memgraph11.3×
  • Neo4j4.19×
  • HelixDBn/a
numerics
6 workloads
WinnerKuzu
LoraDB1.08× slower
  • Kuzufastest
  • Grafeo1.87×
  • SurrealDB39.9×
  • Memgraph10.7×
  • Neo4j4.00×
  • HelixDB20.4×
aggregates
9 workloads
WinnerLoraDB
LoraDBfastest
  • Kuzu3.18×
  • Grafeo1.89×
  • SurrealDB44.7×
  • Memgraph6.25×
  • Neo4j6.94×
  • HelixDB35.5×
pipeline
9 workloads
WinnerLoraDB
LoraDBfastest
  • Kuzu1.27×
  • Grafeo1.30×
  • SurrealDB36.8×
  • Memgraph4.97×
  • Neo4j3.07×
  • HelixDB17.2×
lists
3 workloads
WinnerLoraDB
LoraDBfastest
  • Kuzu11.3×
  • Grafeo3.21×
  • SurrealDB32.3×
  • Memgraph41.6×
  • Neo4j42.2×
  • HelixDB15.0×
sort
3 workloads
WinnerLoraDB
LoraDBfastest
  • Kuzu1.41×
  • Grafeo1.60×
  • SurrealDB31.8×
  • Memgraph4.28×
  • Neo4j3.48×
  • HelixDB16.4×
traversals
15 workloads
WinnerLoraDB
LoraDBfastest
  • Kuzu20.4×
  • Grafeo5.88×
  • SurrealDB110×
  • Memgraph22.4×
  • Neo4j17.8×
  • HelixDB133×
patterns
4 workloads
WinnerLoraDB
LoraDBfastest
  • Kuzu2.80×
  • Grafeo2.45×
  • SurrealDB190×
  • Memgraph7.59×
  • Neo4j4.96×
  • HelixDB22.2×

Summary table

The summary in one table.

Each engine column carries the geometric-mean slowdown of that engine vs the group winner across every workload they share. Empty cells are noted below.

Geometric-mean slowdown by group, lower is better.
WorkloadSizeLoraDBKuzuGrafeoSurrealDBMemgraphNeo4jHelixDBWinner
setup12.70× slower700× slowerfastestomitted904× slower1769× slower1247× slowerGrafeo
writes90.61× slower1.79× slowerfastest28.3× slower3.71× slower7.75× slower125× slowerGrafeo
scans6fastest6.37× slower5.43× slower121× slower27.5× slower24.1× slower287× slowerLoraDB
predicates12fastest1.14× slower1.83× slower21.3× slower4.77× slower3.78× slower20.9× slowerLoraDB
strings51.22× slowerfastest1.84× slower34.1× slower11.3× slower4.19× sloweromittedKuzu
numerics61.08× slowerfastest1.87× slower39.9× slower10.7× slower4.00× slower20.4× slowerKuzu
aggregates9fastest3.18× slower1.89× slower44.7× slower6.25× slower6.94× slower35.5× slowerLoraDB
pipeline9fastest1.27× slower1.30× slower36.8× slower4.97× slower3.07× slower17.2× slowerLoraDB
lists3fastest11.3× slower3.21× slower32.3× slower41.6× slower42.2× slower15.0× slowerLoraDB
sort3fastest1.41× slower1.60× slower31.8× slower4.28× slower3.48× slower16.4× slowerLoraDB
traversals15fastest20.4× slower5.88× slower110× slower22.4× slower17.8× slower133× slowerLoraDB
patterns4fastest2.80× slower2.45× slower190× slower7.59× slower4.96× slower22.2× slowerLoraDB
total82fastest3.30× slower2.30× slower48.6× slower9.75× slower7.99× slower57.2× slowerLoraDB

Per-workload detail

Every workload, every engine, raw timings.

Workload rows show the raw mean time plus the slowdown against the row’s winner. Omitted cells mean the workload has no like-for-like equivalent on that engine; the reason is captured under each group.

setup(1)

WinnerGrafeo
WorkloadSizeLoraDBKuzuGrafeoSurrealDBMemgraphNeo4jHelixDBWinner
construct_empty4.06 µs2.70× slower1.05 ms700× slower1.50 µsfastestomitted1.36 ms904× slower2.66 ms1769× slower1.87 ms1247× slowerGrafeo

writes(9)

WinnerGrafeo
WorkloadSizeLoraDBKuzuGrafeoSurrealDBMemgraphNeo4jHelixDBWinner
bulk_edges200606.63 µsfastest2.01 ms3.31× slower19.86 ms32.7× sloweromitted3.18 ms5.24× slower2.65 ms4.37× slower309.68 ms510× slowerLoraDB
bulk_set_match1000552.39 µs1.84× slower300.03 µsfastest315.88 µs1.05× slower6.15 ms20.5× slower726.92 µs2.42× slower916.11 µs3.05× slower3.57 ms11.9× slowerKuzu
delete_node1000355.70 µs1.47× slower598.35 µs2.48× slower241.43 µsfastest5.56 ms23.0× slower483.58 µs2.00× slower1.65 ms6.84× slower151.74 ms629× slowerGrafeo
merge_create1000112.57 µs1.25× slower670.68 µs7.45× slower90.02 µsfastestomitted677.96 µs7.53× slower2.48 ms27.6× sloweromittedGrafeo
merge_existing100023.95 µs2.89× slower162.06 µs19.6× slower8.29 µsfastestomitted304.94 µs36.8× slower647.72 µs78.1× sloweromittedGrafeo
set_multiple_props100021.15 µsfastest169.72 µs8.03× slower182.77 µs8.64× slower5.54 ms262× slower313.89 µs14.8× slower571.61 µs27.0× slower2.37 ms112× slowerLoraDB
update_set100018.01 µsfastest188.62 µs10.5× slower208.61 µs11.6× slower6.04 ms335× slower315.49 µs17.5× slower732.47 µs40.7× slower2.91 ms162× slowerLoraDB
write_bulk10001.46 ms1.93× slower2.76 ms3.65× slower756.21 µsfastest26.66 ms35.3× slower3.13 ms4.14× slower6.34 ms8.38× slower771.22 ms1020× slowerGrafeo
write_single100014.90 µs2.20× sloweromitted6.78 µsfastest252.56 µs37.3× slower413.52 µs61.0× slower1.30 ms192× slower153.86 ms22704× slowerGrafeo
Omissions

Workloads omitted only where the engine has no like-for-like equivalent — a missing scalar function, a different MERGE semantics, a reserved word. The reason is recorded with the workload, not silently dropped.

  • write_single
    Kuzu
    • Kuzu requires `CREATE NODE TABLE` before inserts; the empty fixture has no schema and adding one would change the iteration's measured cost.
  • merge_existing
    HelixDBSurrealDB
    • HelixDB has no MERGE/upsert; emulating it needs conditional var_as_if branching.
    • SurrealDB's UPSERT semantics diverge from Cypher MERGE on which fields are matched vs set.
  • merge_create
    HelixDBSurrealDB
    • HelixDB has no MERGE/upsert (see merge_existing).
    • See merge_existing — UPSERT semantics differ.
  • bulk_edges
    SurrealDB
    • UNWIND-driven bulk RELATE requires scripted FOR loops; not a like-for-like comparison.

scans(6)

WinnerLoraDB
WorkloadSizeLoraDBKuzuGrafeoSurrealDBMemgraphNeo4jHelixDBWinner
distinct1000198.38 µsfastest448.06 µs2.26× slower246.37 µs1.24× sloweromitted738.04 µs3.72× slower566.24 µs2.85× sloweromittedLoraDB
lookup_by_id1000716.64 nsfastest116.07 µs162× slower170.03 µs237× slower5.26 ms7340× slower305.39 µs426× slower601.36 µs839× slower2.30 ms3205× slowerLoraDB
lookup_by_id_indexed1000684.00 nsfastest116.18 µs170× slower22.73 µs33.2× slower32.35 µs47.3× slower310.02 µs453× slower747.01 µs1092× slower2.62 ms3831× slowerLoraDB
range_filter1000199.70 µs1.04× slower192.68 µsfastest214.22 µs1.11× slower9.29 ms48.2× slower1.22 ms6.31× slower589.16 µs3.06× sloweromittedKuzu
scan_filtered1000149.08 µsfastest158.49 µs1.06× slower211.95 µs1.42× slower5.88 ms39.5× slower1.15 ms7.73× slower718.45 µs4.82× slower3.82 ms25.6× slowerLoraDB
scan_label1000124.96 µsfastest131.34 µs1.05× slower213.71 µs1.71× slower5.01 ms40.1× slower1.61 ms12.9× slower661.84 µs5.30× slower2.70 ms21.6× slowerLoraDB
Omissions

Workloads omitted only where the engine has no like-for-like equivalent — a missing scalar function, a different MERGE semantics, a reserved word. The reason is recorded with the workload, not silently dropped.

  • distinct
    HelixDBSurrealDB
    • HelixDB's dedup is node-level; there is no SELECT DISTINCT <property>.
    • `value` is a reserved word in SurrealQL's SELECT VALUE clause; no clean equivalent.

predicates(12)

WinnerLoraDB
WorkloadSizeLoraDBKuzuGrafeoSurrealDBMemgraphNeo4jHelixDBWinner
where_compound_and_or1000213.07 µsfastest230.83 µs1.08× slower646.50 µs3.03× slower10.23 ms48.0× slower997.22 µs4.68× slower584.96 µs2.75× slower3.23 ms15.2× slowerLoraDB
where_contains1000145.04 µsfastest166.24 µs1.15× slower255.53 µs1.76× slower4.96 ms34.2× slower638.95 µs4.41× slower597.31 µs4.12× slower3.02 ms20.8× slowerLoraDB
where_ends_with1000143.60 µsfastest167.41 µs1.17× slower236.22 µs1.64× slower5.06 ms35.2× slower726.66 µs5.06× slower581.26 µs4.05× slower2.99 ms20.8× slowerLoraDB
where_id_in_range1000142.71 µs2.02× slower187.97 µs2.66× slower70.55 µsfastest7.54 ms107× slower433.95 µs6.15× slower663.12 µs9.40× slower3.13 ms44.3× slowerGrafeo
where_in_list1000162.42 µsfastest196.06 µs1.21× slower270.30 µs1.66× slower5.59 ms34.4× slower606.63 µs3.74× slower627.53 µs3.86× slower2.92 ms18.0× slowerLoraDB
where_modulo_eq1000127.32 µsfastest167.83 µs1.32× slower250.88 µs1.97× slower128.48 µs1.01× slower717.29 µs5.63× slower557.09 µs4.38× slower3.01 ms23.7× slowerLoraDB
where_not1000166.05 µs1.01× slower164.07 µsfastest340.52 µs2.08× slower8.27 ms50.4× slower1.24 ms7.57× slower695.07 µs4.24× slower4.64 ms28.3× slowerKuzu
where_or1000147.16 µsfastest185.19 µs1.26× slower450.08 µs3.06× slower8.43 ms57.3× slower627.82 µs4.27× slower603.10 µs4.10× slower3.29 ms22.3× slowerLoraDB
where_starts_with1000146.91 µsfastest168.08 µs1.14× slower249.22 µs1.70× slower5.12 ms34.9× slower727.06 µs4.95× slower596.02 µs4.06× slower3.29 ms22.4× slowerLoraDB
where_string_gte1000180.97 µs1.07× slower168.40 µsfastest247.34 µs1.47× slower6.05 ms35.9× slower1.20 ms7.10× slower612.78 µs3.64× slower4.11 ms24.4× slowerKuzu
where_subexpr1000227.59 µs1.69× slower194.85 µs1.45× slower589.01 µs4.37× slower134.71 µsfastest1.76 ms13.1× slower584.16 µs4.34× slower4.73 ms35.1× slowerSurrealDB
where_two_props1000152.69 µsfastest205.41 µs1.35× slower404.15 µs2.65× slower6.46 ms42.3× slower390.30 µs2.56× slower589.64 µs3.86× slower2.56 ms16.8× slowerLoraDB

strings(5)

WinnerKuzu
WorkloadSizeLoraDBKuzuGrafeoSurrealDBMemgraphNeo4jHelixDBWinner
string_concat1000186.55 µs1.27× slower147.24 µsfastest283.23 µs1.92× slower5.86 ms39.8× slower1.68 ms11.4× slower577.43 µs3.92× sloweromittedKuzu
string_size1000172.17 µs1.10× slower156.38 µsfastest251.12 µs1.61× slower5.23 ms33.5× slower1.70 ms10.9× slower567.80 µs3.63× sloweromittedKuzu
string_substring1000210.20 µs1.21× slower173.57 µsfastest314.23 µs1.81× slower5.58 ms32.1× slower2.06 ms11.9× slower877.36 µs5.05× sloweromittedKuzu
string_to_lower1000201.00 µs1.33× slower151.22 µsfastest297.66 µs1.97× slower5.03 ms33.3× slower1.72 ms11.4× slower684.21 µs4.52× sloweromittedKuzu
string_to_upper1000185.41 µs1.22× slower151.96 µsfastest292.95 µs1.93× slower4.91 ms32.3× slower1.67 ms11.0× slower603.96 µs3.97× sloweromittedKuzu
Omissions

Workloads omitted only where the engine has no like-for-like equivalent — a missing scalar function, a different MERGE semantics, a reserved word. The reason is recorded with the workload, not silently dropped.

  • string_to_upper
    HelixDB
    • HelixDB's DSL has no scalar string functions (upper/lower/substring/length/concat) — only property filters and graph traversal.
  • string_to_lower
    HelixDB
    • No scalar string functions in the DSL (see string_to_upper).
  • string_substring
    HelixDB
    • No scalar string functions in the DSL (see string_to_upper).
  • string_size
    HelixDB
    • No scalar string functions in the DSL (see string_to_upper).
  • string_concat
    HelixDB
    • No scalar string functions in the DSL (see string_to_upper).

numerics(6)

WinnerKuzu
WorkloadSizeLoraDBKuzuGrafeoSurrealDBMemgraphNeo4jHelixDBWinner
numeric_abs1000174.85 µs1.13× slower154.99 µsfastest272.48 µs1.76× slower5.86 ms37.8× slower1.64 ms10.6× slower636.05 µs4.10× sloweromittedKuzu
numeric_ceil1000171.69 µs1.10× slower155.40 µsfastest269.13 µs1.73× slower5.81 ms37.4× slower1.78 ms11.5× slower634.65 µs4.08× sloweromittedKuzu
numeric_floor1000175.48 µs1.10× slower159.62 µsfastest326.82 µs2.05× slower5.99 ms37.5× slower1.64 ms10.3× slower609.30 µs3.82× sloweromittedKuzu
numeric_modulo1000144.95 µs1.02× slower142.67 µsfastest236.39 µs1.66× sloweromitted1.59 ms11.2× slower637.61 µs4.47× slower2.97 ms20.8× slowerKuzu
numeric_pow1000166.22 µs1.16× slower143.34 µsfastest394.61 µs2.75× slower8.42 ms58.8× slower1.68 ms11.7× slower641.94 µs4.48× slower2.87 ms20.0× slowerKuzu
numeric_round1000180.68 µsfastest181.69 µs1.01× slower269.75 µs1.49× slower5.87 ms32.5× slower1.68 ms9.30× slower581.78 µs3.22× sloweromittedLoraDB
Omissions

Workloads omitted only where the engine has no like-for-like equivalent — a missing scalar function, a different MERGE semantics, a reserved word. The reason is recorded with the workload, not silently dropped.

  • numeric_abs
    HelixDB
    • HelixDB's Expr supports +,-,*,/,% but no abs/floor/ceil/round.
  • numeric_modulo
    SurrealDB
    • SurrealQL parser rejects bare `%` inside SELECT projections (same parse limit as grouped_aggregation).
  • numeric_floor
    HelixDB
    • HelixDB's Expr supports +,-,*,/,% but no abs/floor/ceil/round.
  • numeric_ceil
    HelixDB
    • HelixDB's Expr supports +,-,*,/,% but no abs/floor/ceil/round.
  • numeric_round
    HelixDB
    • HelixDB's Expr supports +,-,*,/,% but no abs/floor/ceil/round.

aggregates(9)

WinnerLoraDB
WorkloadSizeLoraDBKuzuGrafeoSurrealDBMemgraphNeo4jHelixDBWinner
aggregate_avg100081.43 µsfastest253.54 µs3.11× slower202.26 µs2.48× slower6.22 ms76.4× slower562.93 µs6.91× slower606.76 µs7.45× slower3.20 ms39.3× slowerLoraDB
aggregate_collect100078.90 µsfastest275.13 µs3.49× slower214.58 µs2.72× slower6.79 ms86.0× slower599.26 µs7.60× slower619.24 µs7.85× sloweromittedLoraDB
aggregate_count100059.50 µs2.77× slower250.00 µs11.7× slower21.44 µsfastest209.05 µs9.75× slower381.02 µs17.8× slower588.34 µs27.4× sloweromittedGrafeo
aggregate_count_distinct1000104.05 µsfastest441.70 µs4.24× slower213.10 µs2.05× sloweromitted540.27 µs5.19× slower635.68 µs6.11× sloweromittedLoraDB
aggregate_max100079.97 µsfastest263.33 µs3.29× slower200.95 µs2.51× slower6.08 ms76.0× slower572.73 µs7.16× slower619.56 µs7.75× slower2.86 ms35.7× slowerLoraDB
aggregate_min100079.67 µsfastest258.01 µs3.24× slower197.17 µs2.47× slower5.95 ms74.7× slower552.13 µs6.93× slower563.60 µs7.07× slower2.49 ms31.3× slowerLoraDB
aggregate_sum100078.09 µsfastest263.06 µs3.37× slower199.65 µs2.56× slower6.23 ms79.8× slower524.56 µs6.72× slower568.81 µs7.28× slower2.82 ms36.1× slowerLoraDB
grouped_aggregation1000154.46 µsfastest549.19 µs3.56× slower269.45 µs1.74× sloweromitted751.51 µs4.87× slower969.01 µs6.27× sloweromittedLoraDB
top_k1000186.50 µsfastest248.58 µs1.33× slower424.61 µs2.28× slower6.40 ms34.3× slower955.44 µs5.12× slower792.15 µs4.25× sloweromittedLoraDB
Omissions

Workloads omitted only where the engine has no like-for-like equivalent — a missing scalar function, a different MERGE semantics, a reserved word. The reason is recorded with the workload, not silently dropped.

  • aggregate_count
    HelixDB
    • The HelixDB enterprise-dev image rejects `count()` dynamic queries with `rate limit exceeded` (its other 9 workloads run fine). The count handler is wired in helixdb.rs and would run on a server without that limit.
  • aggregate_collect
    HelixDB
    • aggregate_by offers Count/Sum/Min/Max/Mean, no list collect.
  • aggregate_count_distinct
    HelixDBSurrealDB
    • Needs count(DISTINCT); count() is rate-limited on the enterprise-dev image and value-level DISTINCT isn't exposed.
    • count(DISTINCT) has no direct SurrealQL aggregate; requires nested SELECT + array::distinct.
  • grouped_aggregation
    HelixDBSurrealDB
    • group_count groups by a stored property, not a computed value % 10 key.
    • SurrealQL rejects `%` inside a SELECT projection that's then used as a GROUP BY key (parse error).

pipeline(9)

WinnerLoraDB
WorkloadSizeLoraDBKuzuGrafeoSurrealDBMemgraphNeo4jHelixDBWinner
case_when1000173.33 µsfastest186.25 µs1.07× slower256.32 µs1.48× slower7.38 ms42.6× slower1.86 ms10.8× slower796.60 µs4.60× slower2.78 ms16.1× slowerLoraDB
coalesce_existing1000161.92 µsfastest162.41 µs1.00× slower260.13 µs1.61× slower7.51 ms46.4× slower1.62 ms9.99× slower628.36 µs3.88× slower3.32 ms20.5× slowerLoraDB
computed_in_return1000151.15 µs1.07× slower140.92 µsfastest241.22 µs1.71× slower7.35 ms52.1× slower1.61 ms11.5× slower639.09 µs4.54× slower2.99 ms21.2× slowerKuzu
distinct_with_order1000508.01 µs2.08× slower549.89 µs2.25× slower243.88 µsfastestomitted692.42 µs2.84× slower617.76 µs2.53× sloweromittedGrafeo
predicate_via_function1000238.39 µs1.38× slower172.38 µsfastest434.70 µs2.52× slower7.45 ms43.2× slower1.77 ms10.3× slower544.38 µs3.16× sloweromittedKuzu
with_aggregate_then_filter1000148.70 µsfastest475.77 µs3.20× slower267.49 µs1.80× sloweromitted567.44 µs3.82× slower710.00 µs4.77× sloweromittedLoraDB
with_distinct_then_count1000202.72 µsfastest540.85 µs2.67× slower244.75 µs1.21× sloweromitted597.19 µs2.95× slower812.09 µs4.01× sloweromittedLoraDB
with_pipeline1000186.41 µsfastest333.60 µs1.79× slower218.95 µs1.17× slower5.98 ms32.1× slower678.15 µs3.64× slower581.26 µs3.12× sloweromittedLoraDB
with_two_chained1000313.64 µs1.41× slower222.76 µsfastest388.95 µs1.75× slower8.12 ms36.5× slower1.22 ms5.46× slower608.48 µs2.73× slower4.25 ms19.1× slowerKuzu
Omissions

Workloads omitted only where the engine has no like-for-like equivalent — a missing scalar function, a different MERGE semantics, a reserved word. The reason is recorded with the workload, not silently dropped.

  • with_pipeline
    HelixDB
    • Returns count(...); count() is rate-limited on the enterprise-dev image (see aggregate_count).
  • with_distinct_then_count
    HelixDBSurrealDB
    • count() rate-limited and no value-level DISTINCT.
    • DISTINCT on `value` needs SELECT VALUE, where `value` is reserved (same parse limit as the `distinct` workload).
  • with_aggregate_then_filter
    HelixDBSurrealDB
    • Group-then-having on a computed key (value % 10) isn't expressible; group_count keys on a stored property.
    • Groups on `value % 10`; SurrealQL rejects `%` in a projection used as a GROUP BY key (same parse limit as grouped_aggregation).
  • predicate_via_function
    HelixDB
    • WHERE size(name) needs a length() scalar the DSL doesn't provide.
  • distinct_with_order
    HelixDBSurrealDB
    • No value-level DISTINCT (see distinct).
    • DISTINCT + ORDER BY on `value`, which is reserved in both SELECT VALUE and ORDER BY (see distinct, order_by_multi_key).

lists(3)

WinnerLoraDB
WorkloadSizeLoraDBKuzuGrafeoSurrealDBMemgraphNeo4jHelixDBWinner
list_in_construction1000177.94 µs1.05× slower168.89 µsfastest450.42 µs2.67× slower6.14 ms36.4× slower2.05 ms12.1× slower733.38 µs4.34× slower2.67 ms15.8× slowerKuzu
list_unwind_explicit10001.11 µsfastest165.87 µs149× slower7.11 µs6.40× slower33.52 µs30.2× slower322.60 µs291× slower689.53 µs621× sloweromittedLoraDB
range_function100018.86 µsfastest193.49 µs10.3× slower38.62 µs2.05× sloweromitted404.85 µs21.5× slower555.15 µs29.4× sloweromittedLoraDB
Omissions

Workloads omitted only where the engine has no like-for-like equivalent — a missing scalar function, a different MERGE semantics, a reserved word. The reason is recorded with the workload, not silently dropped.

  • range_function
    SurrealDB
    • SurrealQL has no row-generating numeric range (no UNWIND/range equivalent); the explicit-list unwind is covered by list_unwind_explicit.

sort(3)

WinnerLoraDB
WorkloadSizeLoraDBKuzuGrafeoSurrealDBMemgraphNeo4jHelixDBWinner
order_by_id_asc1000167.95 µsfastest234.56 µs1.40× slower226.74 µs1.35× slower5.24 ms31.2× slower738.63 µs4.40× slower718.84 µs4.28× slower3.20 ms19.1× slowerLoraDB
order_by_multi_key1000211.99 µsfastest276.69 µs1.31× slower442.71 µs2.09× sloweromitted871.82 µs4.11× slower554.84 µs2.62× slower2.80 ms13.2× slowerLoraDB
skip_limit1000162.19 µsfastest251.28 µs1.55× slower233.92 µs1.44× slower5.24 ms32.3× slower704.66 µs4.34× slower612.55 µs3.78× slower2.87 ms17.7× slowerLoraDB
Omissions

Workloads omitted only where the engine has no like-for-like equivalent — a missing scalar function, a different MERGE semantics, a reserved word. The reason is recorded with the workload, not silently dropped.

  • order_by_multi_key
    SurrealDB
    • `value` is reserved in SurrealQL ORDER BY clauses (parse error).

traversals(15)

WinnerLoraDB
WorkloadSizeLoraDBKuzuGrafeoSurrealDBMemgraphNeo4jHelixDBWinner
direct_record_traversal500831.70 nsfastest255.86 µs308× slower64.09 µs77.1× slower62.98 µs75.7× slower384.41 µs462× slower616.93 µs742× slower1.55 ms1861× slowerLoraDB
recursive_depth2500968.69 nsfastest499.89 µs516× slower62.29 µs64.3× slower110.22 µs114× slower380.49 µs393× slower601.14 µs621× slower1.69 ms1742× slowerLoraDB
recursive_depth35001.04 µsfastest540.33 µs520× slower62.87 µs60.5× slower147.78 µs142× slower382.45 µs368× slower592.76 µs570× slower1.46 ms1402× slowerLoraDB
recursive_depth55001.16 µsfastest511.05 µs440× slower62.30 µs53.7× slower225.94 µs195× slower426.52 µs367× slower606.31 µs522× slower1.65 ms1425× slowerLoraDB
relation_filter500117.78 µsfastest406.36 µs3.45× sloweromitted18.70 ms159× slower868.53 µs7.37× slower586.82 µs4.98× slower2.50 ms21.2× slowerLoraDB
traversal_count_one_hop50059.36 µsfastest288.00 µs4.85× slower141.39 µs2.38× slower106.91 µs1.80× slower394.49 µs6.65× slower609.51 µs10.3× sloweromittedLoraDB
traversal_filter_one_hop500138.99 µsfastest405.25 µs2.92× slower259.07 µs1.86× slower21.51 ms155× slower1.04 ms7.49× slower582.58 µs4.19× slower3.15 ms22.7× slowerLoraDB
traversal_one_hop500125.98 µsfastest360.18 µs2.86× slower263.65 µs2.09× slower25.78 ms205× slower1.14 ms9.06× slower570.56 µs4.53× slower2.59 ms20.5× slowerLoraDB
traversal_reverse500123.67 µsfastest365.12 µs2.95× slower266.69 µs2.16× slower24.71 ms200× slower1.10 ms8.93× slower591.25 µs4.78× slower2.62 ms21.2× slowerLoraDB
traversal_three_hop500236.10 µsfastest1.13 ms4.80× slower556.10 µs2.36× slower60.59 ms257× slower1.23 ms5.21× slower607.69 µs2.57× slower5.16 ms21.9× slowerLoraDB
traversal_two_hop500165.58 µsfastest649.69 µs3.92× slower411.83 µs2.49× slower44.18 ms267× slower1.27 ms7.66× slower555.27 µs3.35× slower64.61 ms390× slowerLoraDB
traversal_undirected500213.41 µsfastest492.51 µs2.31× slower494.10 µs2.32× sloweromitted1.76 ms8.26× slower637.72 µs2.99× slower4.20 ms19.7× slowerLoraDB
variable_length_path10086.24 µsfastest2.64 ms30.6× slower210.43 µs2.44× sloweromitted809.87 µs9.39× slower605.82 µs7.02× sloweromittedLoraDB
varlen_2_to_5100123.74 µsfastest3.90 ms31.5× slower274.33 µs2.22× sloweromitted986.89 µs7.98× slower578.29 µs4.67× sloweromittedLoraDB
varlen_exact_510056.89 µsfastest3.86 ms67.9× slower140.52 µs2.47× sloweromitted576.13 µs10.1× slower586.35 µs10.3× sloweromittedLoraDB
Omissions

Workloads omitted only where the engine has no like-for-like equivalent — a missing scalar function, a different MERGE semantics, a reserved word. The reason is recorded with the workload, not silently dropped.

  • traversal_undirected
    SurrealDB
    • SurrealDB graph edges are directional; the undirected `-[:NEXT]-` pattern has no single like-for-like arrow form (forward and reverse are covered by traversal_one_hop and traversal_reverse).
  • variable_length_path
    HelixDBSurrealDB
    • Range-bounded variable-length expansion isn't mapped; fixed depths are benched as recursive_depth2/3/5.
    • SurrealQL recursive traversal takes a fixed depth `@{n}` (see recursive_depth2/3/5); a `1..3` range expanded from every start node has no like-for-like form.
  • varlen_2_to_5
    HelixDBSurrealDB
    • Range-bounded variable-length expansion isn't mapped (see variable_length_path).
    • Range-bounded variable-length expansion from every start node; see variable_length_path.
  • varlen_exact_5
    HelixDBSurrealDB
    • Range-bounded variable-length expansion isn't mapped (see variable_length_path).
    • Fixed-depth expansion from every start node; the anchored single-source equivalent is benched as recursive_depth5.
  • relation_filter
    Grafeo
    • grafeo's `create_edge` facade takes no edge properties, so the chain fixture has no `step` to filter on. memgraph/neo4j/kuzu seed `step` directly, so they do run this workload.

patterns(4)

WinnerLoraDB
WorkloadSizeLoraDBKuzuGrafeoSurrealDBMemgraphNeo4jHelixDBWinner
edge_subquery_clause500213.55 µsfastest465.09 µs2.18× sloweromitted18.19 ms85.2× slower1.18 ms5.52× slower605.92 µs2.84× slower4.12 ms19.3× slowerLoraDB
star_fanout1000138.96 µsfastest296.68 µs2.13× slower321.31 µs2.31× slower29.94 ms215× slower1.62 ms11.7× slower579.41 µs4.17× slower2.75 ms19.8× slowerLoraDB
star_fanout_count100061.36 µsfastest290.42 µs4.73× slower193.38 µs3.15× slower20.35 ms332× slower500.19 µs8.15× slower590.08 µs9.62× sloweromittedLoraDB
star_fanout_filter1000112.53 µsfastest312.37 µs2.78× slower227.60 µs2.02× slower24.13 ms214× slower707.87 µs6.29× slower599.26 µs5.33× slower3.24 ms28.8× slowerLoraDB
Omissions

Workloads omitted only where the engine has no like-for-like equivalent — a missing scalar function, a different MERGE semantics, a reserved word. The reason is recorded with the workload, not silently dropped.

  • star_fanout_count
    HelixDB
    • The HelixDB enterprise-dev image rejects `count()` dynamic queries with `rate limit exceeded` (its other 9 workloads run fine); see aggregate_count.
  • edge_subquery_clause
    Grafeo
    • grafeo's `create_edge` facade takes no edge properties, so the social fixture has no `strength` to filter on. memgraph/neo4j/kuzu seed `strength` directly, so they do run this workload.

Methodology

What this benchmark does and doesn’t say.

What’s measured

Mean iteration time on identical fixtures. Engines run the same query semantics where the language allows expressing them; where it doesn’t, the workload is marked omitted with the reason recorded next to it. Geometric mean is used at the group level so a single outlier doesn’t dominate the row.

What this isn’t

Not a production-scale TPC benchmark. Not a load test. Not a comparison of operational footprint or durability — every engine is run in-process or against a local server with the same warm fixture each iteration. Workloads are micro-benchmarks of the query pipeline, not of full systems.

Where to dig in

The full source — fixtures, harness, per-engine glue — lives in comparisons/. The report itself is generated from a single Criterion run; re-running the suite regenerates report.md, which this page is derived from.