You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Support "A column is known to be entirely NULL" in PruningPredicate #9171
A predicate like col_a != A AND col_b='bananas' can not be true for File 1 (as col_B is logically NULL for all rows)
This is subtly, but importantly different than the case when nothing is known about the column, which confusingly is encoded by returning NULL from PruningStatistics::min_values()
Describe the solution you'd like
Add a new method PruningStatistics::row_counts() to get the total row counts in each container.
Use the information from PruningStatistics::row_counts() and PruningStatistics::null_counts() to determine containers where columns are entirely NULL
Rewrite the predicate, replacing references to columns known to be NULL with a NULL literal and try to simplify the expressions (e.g. a = 5 --> NULL = 5 --> NULL)
For the example in this ticket's description with predicate col_a != A AND col_b='bananas' where col_b is not known and the relevant container had 100 rows,
the relevant PruningStatistics would return col_b: {null_count = 100, row_count = 100}
PruningPredicate::prune would determine col_b was entirely null, and would rewrite the predicate to be col_a != A AND NULL = 'bananas'.
The pruning rewrite would happen again, and this time would not try to fetch min/max statistics for col_b and thus could be proven to be not true.
That would be the more elegant (but likely much more substantial) solution in my opinion
I'm interested in rewriting pruning predicate to use the range analysis! For now, I'm still writing in PhysicalExpr just to see how the code works. It would be nice to refactor into range analysis after I sort out basic logics
After discussion with @alamb, we plan to do the implementation in two phases (i.e. two PRs):
Turn each sub expression into a case expression
Simplify the case expression and make it easy to read
1. Turn each sub expression into a case expression
Each sub expression will be rewritten into a case expression instead of wrapping the entire expression into one case expression. Each sub expression has its own case expression will make sure the pruning predict rewrite logic is correct.
For example, x < 5 AND x > 0 OR y = 10
will be rewritten into
# x < 5
CASE
WHEN x_null_count = x_row_count THEN false
ELSE x_max <5
END
AND# x > 0
CASE
WHEN x_null_count = x_row_count THEN false
ELSE 0< x_min
END
OR# y = 10
CASE
WHEN y_null_count = y_row_count THEN false
ELSE y_min <=10AND10<= y_max
END
2. Simplify the case expression and make it easy to read
The above example is formatted in a way that's easy to read. In the actual pruning predicate string, there is no new lines and indentation. The above example looks like this in the query explain:
CASE WHEN x_null_count = x_row_count THEN false ELSE x_max < 5 END AND CASE WHEN x_null_count = x_row_count THEN false ELSE 0 < x_min END OR CASE WHEN y_null_count = y_row_count THEN false ELSE y_min <= 10 AND 10 <= y_max END
As you can see, the final pruning predict rewrite can be long and hard to read. Therefore, we need phase 2 to improve the readability.
Probably add format, like () and new lines to the expression string. I will have a better idea after phase 1 PR is done
Activity
[-]Support [/-][+]Support "A column is known to be entirely NULL" in `PruningPredicate`[/+]alamb commentedon Feb 9, 2024
cc @appletreeisyellow
appletreeisyellow commentedon Feb 9, 2024
Thank you @alamb!
One question for this line:
Do you actually mean:
File 2:
col_a,col_b(col_bwas added later)alamb commentedon Feb 9, 2024
Yes, I have update the ticket. Thank you
appletreeisyellow commentedon Feb 9, 2024
Thanks for verifying. I plan to work on this issue
alamb commentedon Feb 11, 2024
One thought I had about this feature was to consider writing predicates like
Instead of
To something like
where
y_row_countis a new column based on the value ofPruningStatistics::row_countsI think this would only be valid for top level expressions in the
ANDclause (not any arbitrary sub expression)alamb commentedon Feb 11, 2024
It might also now be a good time to look into how we could rewrite pruning predicate to use the range analysis in https://docs.rs/datafusion/latest/datafusion/physical_expr/intervals/cp_solver/index.html 🤔
That would be the more elegant (but likely much more substantial) solution in my opinion
appletreeisyellow commentedon Feb 13, 2024
Do you mean something like this?
For example, rewriting a complicated predicate like
x < 5 AND x > 0instead of
To something like (a)
I don't think we want it to be (b)
appletreeisyellow commentedon Feb 13, 2024
I think case expression can be wrapped around the
ORclause as well. For example,x = 8 OR x < 0can be rewrite intoIf we know that a container has column
xto be entirelyNULL, this container can be skipped, regardless the result ofORclause is true or false.appletreeisyellow commentedon Feb 13, 2024
For a predicate with more than one columns, we might want to have a WHEN clause for each column.
For example, rewriting a predicate like
x < 5 AND x > 0 AND y = 10intoappletreeisyellow commentedon Feb 13, 2024
I'm interested in rewriting pruning predicate to use the range analysis! For now, I'm still writing in
PhysicalExprjust to see how the code works. It would be nice to refactor into range analysis after I sort out basic logicsappletreeisyellow commentedon Feb 14, 2024
After discussion with @alamb, we plan to do the implementation in two phases (i.e. two PRs):
1. Turn each sub expression into a case expression
Each sub expression will be rewritten into a case expression instead of wrapping the entire expression into one case expression. Each sub expression has its own case expression will make sure the pruning predict rewrite logic is correct.
For example,
x < 5 AND x > 0 OR y = 10will be rewritten into
2. Simplify the case expression and make it easy to read
The above example is formatted in a way that's easy to read. In the actual pruning predicate string, there is no new lines and indentation. The above example looks like this in the query explain:
CASE WHEN x_null_count = x_row_count THEN false ELSE x_max < 5 END AND CASE WHEN x_null_count = x_row_count THEN false ELSE 0 < x_min END OR CASE WHEN y_null_count = y_row_count THEN false ELSE y_min <= 10 AND 10 <= y_max ENDAs you can see, the final pruning predict rewrite can be long and hard to read. Therefore, we need phase 2 to improve the readability.
Probably add format, like
()and new lines to the expression string. I will have a better idea after phase 1 PR is doneappletreeisyellow commentedon Feb 26, 2024
There is a draft PR: #9223. The major feature is implemented, but there are two things I plan to do before I open it for review (see details).
I plan to continue the work on the week of March 4, 2024.
appletreeisyellow commentedon Mar 14, 2024
Here is an update of the plan
1. Turn each sub expression into a case expression
Implemented in #9223
2. Simplify the case expression and make it easy to read
To be implemented in a follow-up PR:
PruningPredicate#9223 (comment)PruningPredicate#9223 (comment)wrap_case_exprintoPruningExpressionBuilderSupport "A column is known to be entirely NULL" inPruningPredicate#9223 (comment)alamb commentedon Mar 22, 2024
I think this feature is done now that #9223 (comment) is merged so resolving this ticket
@appletreeisyellow if you plan additional work, let's track them in follow on tickets