Repository navigation
Description
Missed optimization: redundant AND-true OR-false branch raises ArcadeDB PROFILE rows
I found a missed optimization opportunity: adding the semantically redundant predicate base AND true OR false AND expr changes the execution plan and raises PROFILE rows, although the base and transformed queries return the same results.
ArcadeDB Version: ArcadeDB 26.6.1-SNAPSHOT, Docker image arcadedata/arcadedb:latest, digest sha256:67979318134d1ae026de78a9b5b5e5800062387ff0a6fc44f414dffb7b53f619
Operating System: macOS Darwin 25.3.0 arm64
Installation Method: Docker image arcadedata/arcadedb:latest, ports 127.0.0.1:2480 -> 2480 and 127.0.0.1:7690 -> 7687
API/Driver: ArcadeDB HTTP API with opencypher
Steps to reproduce
- Load the attached graph setup file into an empty disposable database:
BUG001_reproducer_graph.cypher.txt
# Execute each Cypher statement from BUG001_reproducer_graph.cypher.txt against an empty ArcadeDB database.- Verify the graph size:
MATCH (n) RETURN count(n) AS nodes;
-- nodes: 1280
MATCH ()-[r]->() RETURN count(r) AS relationships;
-- relationships: 1190- Run the base query with the native profile command:
PROFILE
MATCH (n0 :L1)
WHERE ((n0.k5) = -1862396709)
UNWIND [(n0.k6), (n0.k10)] AS a0
RETURN 1 AS a1;- Run the transformed query with the native profile command:
PROFILE
MATCH (n0 :L1)
WHERE ((n0.k5) = -1862396709) AND true OR false AND (n0.k5 IS NULL OR n0.k5 IS NOT NULL)
UNWIND [(n0.k6), (n0.k10)] AS a0
RETURN 1 AS a1;The transformed query is built by rewriting the target WHERE predicate as:
base AND true OR false AND expr
where base is the original predicate:
((n0.k5) = -1862396709)and expr is:
(n0.k5 IS NULL OR n0.k5 IS NOT NULL)The injected boolean item is redundant because base AND true reduces to base, and false AND expr is always false. Since AND binds tighter than OR, the transformed predicate reduces to base OR false, which is equivalent to the original base predicate.
Expected behavior
The planner should simplify the redundant boolean item before plan construction because the transformed predicate is semantically equivalent to the base predicate. It should avoid retaining predicate residue or introducing extra filters, joins, barriers, scans, row production, memory, or buffer work.
Actual behavior
Both queries return the same result set on the attached graph.
Primary PROFILE metric: rows changed from 3.0 to 36.0; ratio 12.0, delta 33.0.
Base PROFILE excerpt:
OpenCypher Query Profile
========================
Execution Time: 2.600 ms
Rows Returned: 80
Execution Plan (Cost-Based Optimizer):
+ Filter [predicate=n0.k5 = -1862396709, cost=36.00, rows=12]
+ NodeByLabelScan(n0:L1) [cost=24.00, rows=24]
Estimated Cost: 36.00
Estimated Rows: 12
Transformed PROFILE excerpt:
OpenCypher Query Profile
========================
Execution Time: 1.264 ms
Rows Returned: 80
Execution Plan (Cost-Based Optimizer):
+ Filter [predicate=((n0.k5 = -1862396709 AND true) OR (false AND (n0.k5 IS NULL OR n0.k5 IS NOT NULL))), cost=360.00, rows=120]
+ NodeByLabelScan(n0:L1) [cost=240.00, rows=240]
Estimated Cost: 360.00
Estimated Rows: 120
Missed optimization summary: the planner does not reduce base AND true OR false AND expr to the base predicate before planning, so the transformed plan retains predicate residue in a Filter and raises rows from 3.0 to 36.0.
Activity
fix(#4405): simplify AND-true/OR-false boolean constants in Cypher WH…
chore(deps-dev): bump redis.clients:jedis from 7.2.1 to 7.4.0 [skip ci]
fix(ArcadeData#4405): simplify AND-true/OR-false boolean constants in…
fix(#4405): simplify AND-true/OR-false boolean constants in Cypher WH…