Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sql: propagate equalities to optimize JOIN filters further #12892

Closed
knz opened this issue Jan 12, 2017 · 8 comments
Closed

sql: propagate equalities to optimize JOIN filters further #12892

knz opened this issue Jan 12, 2017 · 8 comments
Labels
A-sql-optimizer SQL logical planning and optimizations. A-sql-semantics C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) C-performance Perf of queries or internals. Solution not expected to change functional behavior. O-community Originated from the community
Milestone

Comments

@knz
Copy link
Contributor

knz commented Jan 12, 2017

Pursuant to #12617, suggested by @RaduBerinde, relative to predicates over JOINs

it wouldn't be too hard to also duplicate any vars that refer to right columns which are constrained to be equal to a left column (and vice-versa). This can happen regardless if merged columns exist.

For example SELECT * FROM a JOIN b where a.x = b.y AND b.y > 5 AND b.y < 10. It would be nice for the 5-10 range to make it to the a source.

This entails propagating the equalities to the inequalities, perform range analysis, and propagate the resulting ranges towards the JOIN operands.

@knz knz added C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) C-performance Perf of queries or internals. Solution not expected to change functional behavior. A-sql-semantics labels Jan 12, 2017
@RaduBerinde
Copy link
Member

RaduBerinde commented Jan 12, 2017

This entails propagating the equalities to the inequalities, perform range analysis, and propagate the resulting ranges towards the JOIN operands.

My suggestion was not around range analysis and such, but simply to allow splitFilter to convert between left and right IndexVars that we know are equal. If the splitFilter callback knows that b.y is the same as a.x, it can go from
a.x = b.y AND b.y > 5 AND b.y < 10 to a leftExpr of a.x > 5 AND a.x < 10.

It's not clear how to calculate the remaining filter (the part that can't be pushed down) with this method, but we can be less functional on that part (it's not a big deal if it's not as small as possible, as long as it disappears in common cases where it needs to disappear).

@knz
Copy link
Contributor Author

knz commented Jun 13, 2017

Even equalities should be propagated.

@bdarnell reports:

root@:26257/test> explain select * from customer join orders on (customer.id=orders.customer_id) where customer.id='x';
+-------+------+----------+----------------------+
| Level | Type |  Field   |     Description      |
+-------+------+----------+----------------------+
|     0 | join |          |                      |
|     0 |      | type     | inner                |
|     0 |      | equality | (id) = (customer_id) |
|     1 | scan |          |                      |
|     1 |      | table    | customer@primary     |
|     1 |      | spans    | /"x"-/"x\x00"        |
|     1 | scan |          |                      |
|     1 |      | table    | orders@primary       |
|     1 |      | spans    | ALL                  |
+-------+------+----------+----------------------+
(9 rows)
root@:26257/test> explain select * from customer join orders on (customer.id=orders.customer_id) where customer.id='x' and orders.customer_id='x';
+-------+------+----------+----------------------+
| Level | Type |  Field   |     Description      |
+-------+------+----------+----------------------+
|     0 | join |          |                      |
|     0 |      | type     | inner                |
|     0 |      | equality | (id) = (customer_id) |
|     1 | scan |          |                      |
|     1 |      | table    | customer@primary     |
|     1 |      | spans    | /"x"-/"x\x00"        |
|     1 | scan |          |                      |
|     1 |      | table    | orders@primary       |
|     1 |      | spans    | /"x"-/"x\x00"        |
+-------+------+----------+----------------------+
(9 rows)

Also my manual optimizations on https://forum.cockroachlabs.com/t/select-query-not-responding/672/32

@bdarnell bdarnell added the O-community Originated from the community label Jun 13, 2017
@petermattis
Copy link
Collaborator

Is there a complexity here that I'm not seeing? Seems like there is a pretty big win on many queries from implementing this.

@knz
Copy link
Contributor Author

knz commented Aug 25, 2017

Yes the complexity is that I still do not understand splitFilter() well enough that I would know where to implement this effectively.

@RaduBerinde
Copy link
Member

The logic would be in the varConvertFunc callback that is passed to splitFilter - if we're trying to get a filter for a and the function knows that a.x = b.y and sees b.y it can convert it to a.x rather than returning !ok.

@petermattis
Copy link
Collaborator

The action is all in planner.addJoinFilter, right? Conceptually straightforward, but after looking at that code I now understand @knz's statement.

@knz
Copy link
Contributor Author

knz commented Aug 25, 2017

Yet I think I understand what Radu is saying :)
I'll have a look next week.

@jordanlewis jordanlewis added the A-sql-optimizer SQL logical planning and optimizations. label Apr 26, 2018
@andy-kimball
Copy link
Contributor

Propagation for this case appears supported by both the heuristic optimizer and the cost-based optimizer. Closing as "Fixed".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-sql-optimizer SQL logical planning and optimizations. A-sql-semantics C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) C-performance Perf of queries or internals. Solution not expected to change functional behavior. O-community Originated from the community
Projects
None yet
Development

No branches or pull requests

7 participants