cockroachdb / cockroachdb/cockroach

opt: rewrite greatest(a, b) < c to (a < c AND b < c)

Open
#119,831 3 comments 0 reactions 0 assignees View on GitHub
A-sql-optimizer C-enhancement E-quick-win O-community T-sql-queries
Dominant language
Go
Stars
32.5k
Forks
4.1k
PR merge metrics
PR metrics pending

Description

**Is your feature request related to a problem? Please describe.**
The index on a table only seems to be used for extremely simple conditionals. For example, consider a table with two integer values, `x` and `y`, indexed on `x`. On an example table, I see the following behavior for a range query:
```
EXPLAIN SELECT * FROM temp WHERE x < 15000;
info
---------------------------------------------------------------------------------------
distribution: local
vectorized: true

• index join
│ estimated row count: 15,047
│ table: temp@primary

└── • scan
estimated row count: 15,047 (15% of the table; stats collected 2 minutes ago)
table: temp@temp_x_idx
spans: (/NULL - /14999]
(11 rows)

Time: 2ms total (execution 2ms / network 0ms)
```
However, for slightly more complicated conditionals, the index is not used, and the estimated row count is very incorrect. For example, if I perform the following (equivalent) query:
```
EXPLAIN SELECT * FROM temp WHERE greatest(x, 3) < 15000;
info
-----------------------------------------------------------------------------------------
distribution: full
vectorized: true

• filter
│ estimated row count: 33,333
│ filter: greatest(x, 3) < 15000

└── • scan
estimated row count: 100,000 (100% of the table; stats collected 3 minutes ago)
table: temp@primary
spans: FULL SCAN
(11 rows)
```
A scan is used and the estimated row count is double what's expected. Here's a more realistic example that also doesn't use the index as I'd expect:
```
EXPLAIN SELECT * FROM temp WHERE greatest(x, y) < 15000;
info
------------------------------------------------------------------------------------------
distribution: full
vectorized: true

• filter
│ estimated row count: 33,333
│ filter: least(x, y) < 15000

└── • scan
estimated row count: 100,000 (100% of the table; stats collected 22 minutes ago)
table: temp@primary
spans: FULL SCAN
(11 rows)

Time: 2ms total (execution 2ms / network 1ms)
```

**Describe the solution you'd like**
I'd expect all three of the above queries to use the index when possible. The optimizer might consider rewriting these expressions, i.e. `greatest(a, b) < c -> a < c AND b < c` and `least(a, b) < c -> a < c OR b < c`. I'm new to cockroachdb, so not sure how much the optimizer already tries to rewrite conditionals, but if I do this `greatest` rewrite manually, I get the index behavior that I expect (i.e. `x < 15000 AND y < 15000` produces a `filter(index join(scan))`).

**Describe alternatives you've considered**
N/A

**Additional context**
N/A

Jira issue: CRDB-36336

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.