Skip to content

Result-equivalent LadyBugDB queries show a 8.0x runtime gap across excluded-middle boolean-redundancy variants #669

Description

@YaeSakuraQ

Ladybug version

v0.18.0

What operating system are you using?

Ubuntu24.04

What happened?

Result-equivalent LadyBugDB queries show a 8.0x runtime gap across excluded-middle boolean-redundancy variants

I found two result-equivalent LadyBugDB query formulations whose measured runtime differs substantially on the attached graph. The intended difference between the formulations is an excluded-middle boolean-redundancy variant.

I am reporting the observed runtime/profile difference without assigning it to a specific LadyBugDB component.

Steps to reproduce

  1. Load the attached graph setup file into an empty disposable graph:
    reproducer_graph.cypher.txt
while IFS= read -r stmt; do ladybugdb-cypher "$stmt"; done < reproducer_graph.cypher.txt
  1. Verify the graph size:
MATCH (n) RETURN count(n) AS nodes;
-- nodes: 128

MATCH ()-[r]->() RETURN count(r) AS relationships;
-- relationships: 73
  1. Run the fast query:
PROFILE
MATCH (n0),
  (n1 :L4 :L1)<-[r0 :T4]-(n2 :L1)<-[r1 :T2]-(n3 :L2)
WHERE (((r0.id) > -1)
  AND ((r0.id) <> (r1.id)))
OPTIONAL MATCH (n0),
  (n4 :L2)-[r2 :T2]->(n3)<-[r3 :T0]-(n5 :L4 :L5),
  (n0)
WHERE ((r0.k61)
  AND ((r2.id) <> (r3.id)))
OPTIONAL MATCH (n0)
WHERE (r2.k47)
OPTIONAL MATCH (n4)-[]->(n3)<-[]-(n5 :L4)
WHERE (r0.k62)
WITH (n5.k32) AS a0,
  (n5.k27) AS a1,
  max('l') AS a2,
  max('x') AS a3,
  (n1.k22) AS a4
WHERE true
RETURN 3 AS a5
  1. Run the slow query:
PROFILE
MATCH (n0),
  (n1 :L4 :L1)<-[r0 :T4]-(n2 :L1)<-[r1 :T2]-(n3 :L2)
WHERE ((((r0.id) > -1)
  AND ((r0.id) <> (r1.id))))
  AND ((((n0.id IS NULL
  OR n0.id IS NOT NULL))
  OR NOT((n0.id IS NULL
  OR n0.id IS NOT NULL)))
  OR (((n0.id IS NULL
  OR n0.id IS NOT NULL)) IS NULL))
OPTIONAL MATCH (n0),
  (n4 :L2)-[r2 :T2]->(n3)<-[r3 :T0]-(n5 :L4 :L5),
  (n0)
WHERE ((r0.k61)
  AND ((r2.id) <> (r3.id)))
OPTIONAL MATCH (n0)
WHERE (r2.k47)
OPTIONAL MATCH (n4)-[]->(n3)<-[]-(n5 :L4)
WHERE (r0.k62)
WITH (n5.k32) AS a0,
  (n5.k27) AS a1,
  max('l') AS a2,
  max('x') AS a3,
  (n1.k22) AS a4
WHERE true
RETURN 3 AS a5

Expected behavior

The two queries are intended to be result-equivalent. On the same graph, I would expect comparable execution time, or at least not a large runtime gap, between these two formulations.

Actual behavior

Repeated replay confirmed that the two queries returned the same result rows and reported a large runtime gap.

Metric Fast query Slow query
Median runtime 35.058 ms 279.600 ms
Runtime ratio 1.000x 7.975x
Runtime delta n/a 244.541 ms

PROFILE plan comparison

Fast query plan excerpt:

Results
    Project / Result collection
        PROFILE aggregate barriers: 9
        Boolean predicate form: baseline formulation

Slow query plan excerpt:

Results
    Project / Result collection
        PROFILE aggregate barriers: 10
        Boolean predicate form: an excluded-middle boolean-redundancy variant
        Operator-family delta versus fast query: Barrier +1, Filter 0, Join 0, Projection 0

Are there known steps to reproduce?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions