Skip to content

perf(optimizer): skip O(n^2) connector simplification when no operands can combine#7687

Open
tobymao wants to merge 1 commit into
mainfrom
perf/simplify-flat-connector-quadratic
Open

perf(optimizer): skip O(n^2) connector simplification when no operands can combine#7687
tobymao wants to merge 1 commit into
mainfrom
perf/simplify-flat-connector-quadratic

Conversation

@tobymao
Copy link
Copy Markdown
Owner

@tobymao tobymao commented May 28, 2026

What

_flat_simplify scans connector operand pairs in O(n²). A pair can only combine when one side is a constant or both are comparisons (see _simplify_connectors / _simplify_comparison), so when no operand is combinable the entire scan is a guaranteed no-op. This adds an early return in that case.

The check lives inside _flat_simplify so it reuses the already-flattened operand queue (no extra traversal) and is gated on exp.Connector, leaving the simplify_equality caller unaffected.

Why

optimize was ~O(n²) in the size of a flat boolean condition. A 1000-term OR of ANDs spent ~1M pairwise _simplify_connectors calls, 0% of them productive (the operands are parenthesized ANDs, which are inert).

Impact

Benchmarks (optimize, best of 5):

input before after
condition_100 67.8ms 54ms
condition_500 648.7ms 297ms 2.2x
condition_1000 2124ms 609ms 3.5x

TPC-H is neutral (verified via interleaved A/B). Output is unchanged — the optimizer and transpile fixtures (which assert exact SQL) pass, and the full unit suite is green.

…s can combine

_flat_simplify scans operand pairs in O(n^2). For connectors, a pair can only
combine when one side is a constant or both are comparisons (see
_simplify_connectors / _simplify_comparison), so when no operand is combinable
the scan is a guaranteed no-op. Returning early in that case avoids the quadratic
blowup on large connectors of inert operands (e.g. a 1000-way OR of ANDs).

The check is placed inside _flat_simplify so it reuses the already-flattened
operand queue (no extra traversal) and is gated on exp.Connector, leaving the
simplify_equality caller unaffected. Output is unchanged.

Benchmarks (optimize, best of 5):
  condition_100:   67.8ms ->  54ms
  condition_500:  648.7ms -> 297ms (2.2x)
  condition_1000: 2124ms  -> 609ms (3.5x)
TPC-H is neutral (verified via interleaved A/B).
@github-actions
Copy link
Copy Markdown
Contributor

SQLGlot Integration Test Results

Comparing:

  • this branch (sqlglot:perf/simplify-flat-connector-quadratic @ sqlglot f181cc5)
  • baseline (main @ sqlglot 07faa10)

By Dialect

dialect main feature branch transitions links
bigquery -> bigquery 24647/24652 passed (100.0%) 23497/23497 passed (100.0%) No change full result / delta
bigquery -> duckdb 870/1154 passed (75.4%) 0/0 passed (0.0%) Results not found full result / delta
duckdb -> duckdb 5823/5823 passed (100.0%) 0/0 passed (0.0%) Results not found full result / delta
snowflake -> duckdb 1125/1857 passed (60.6%) 0/0 passed (0.0%) Results not found full result / delta
snowflake -> snowflake 65203/65232 passed (100.0%) 63027/63027 passed (100.0%) No change full result / delta

Overall

main: 113231 total, 112181 passed (pass rate: 99.1%)

sqlglot:perf/simplify-flat-connector-quadratic: 101037 total, 101037 passed (pass rate: 100.0%)

Transitions:
No change

Dialect pair changes: 0 previous results not found, 3 current results not found

✅ 64 test(s) passed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant