-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Adding basic null predicate support #4943
Adding basic null predicate support #4943
Conversation
Codecov Report
@@ Coverage Diff @@
## master #4943 +/- ##
============================================
- Coverage 56.57% 56.34% -0.23%
Complexity 16 16
============================================
Files 1176 1180 +4
Lines 62835 63068 +233
Branches 9222 9251 +29
============================================
- Hits 35549 35538 -11
- Misses 24643 24881 +238
- Partials 2643 2649 +6
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Minor comments
pinot-common/src/main/java/org/apache/pinot/pql/parsers/pql2/ast/IsNullPredicateAstNode.java
Outdated
Show resolved
Hide resolved
@@ -111,6 +113,15 @@ private static BaseFilterOperator constructPhysicalOperator(FilterQueryTree filt | |||
// Leaf filter operator | |||
Predicate predicate = Predicate.newPredicate(filterQueryTree); | |||
|
|||
// Check for null predicate | |||
Predicate.Type type = predicate.getType(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this code to FilterOperatorUtils.getLeafOperator? we can have an IsPredicateEvaluator that return empty list for matchings and non matching dictIds
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is a little bit hard to model NULL into PredicateEvaluator though, as there is no easy way to hook the nullValueVector into it. I'm okay making this an extra check for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah - couldn't figure out how to do this in predicate evaluator. Leaving it as is for now.
...ore/src/main/java/org/apache/pinot/core/segment/index/readers/NullValueVectorReaderImpl.java
Outdated
Show resolved
Hide resolved
pinot-core/src/main/java/org/apache/pinot/core/plan/FilterPlanNode.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly good except for the thread-safety issue
@@ -111,6 +113,15 @@ private static BaseFilterOperator constructPhysicalOperator(FilterQueryTree filt | |||
// Leaf filter operator | |||
Predicate predicate = Predicate.newPredicate(filterQueryTree); | |||
|
|||
// Check for null predicate | |||
Predicate.Type type = predicate.getType(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is a little bit hard to model NULL into PredicateEvaluator though, as there is no easy way to hook the nullValueVector into it. I'm okay making this an extra check for now.
@@ -39,4 +40,9 @@ public void setNull(int docId) { | |||
public boolean isNull(int docId) { | |||
return _nullBitmap.contains(docId); | |||
} | |||
|
|||
@Override | |||
public ImmutableRoaringBitmap getNullBitmap() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not thread-safe. You might want to use the ThreadSafeMutableRoaringBitmap wrapper in RealtimeInvertedIndexReader
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Jackie-Jiang why do we need that? there is only one thread updating the bitmap and multiple threads reading it. cloning entire bitmap for every access is going to be expensive. when did we do this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kishoreg MutableRoaringBitmap itself is not thread-safe. You cannot read the bitmap while updating it. One possible solution is using ReadWriteLock for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually ReadWriteLock might not work in this case as there are too many reading methods
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't know about this. we should measure the performance impact on the ingestion rate (due to synchronization) and query throughput (bcos to clone). Readwrite lock will not help since its getting updated frequently.
The synchronization is not really needed since only one thread(consumer) is updating it. clone is important.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need synchronization because clone and update cannot happen at the same time either
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missed that. let's create another issue to measure and optimize this.
pinot-core/src/main/java/org/apache/pinot/core/plan/FilterPlanNode.java
Outdated
Show resolved
Hide resolved
...ore/src/main/java/org/apache/pinot/core/segment/index/readers/NullValueVectorReaderImpl.java
Outdated
Show resolved
Hide resolved
- Refactor and use ThreadSafeMutableRoaringBitmap for thread safety - Other minor fixes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
pinot-core/src/main/java/org/apache/pinot/core/plan/FilterPlanNode.java
Outdated
Show resolved
Hide resolved
if (type.equals(Predicate.Type.IS_NULL) || type.equals(Predicate.Type.IS_NOT_NULL)) { | ||
DataSource dataSource = segment.getDataSource(filterQueryTree.getColumn()); | ||
ImmutableRoaringBitmap nullBitmap = dataSource.getNullValueVector().getNullBitmap(); | ||
boolean exclusive = (type == Predicate.Type.IS_NULL) ? false : true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can either change this to boolean exclusive = type != Predicate.Type.IS_NULL or maybe move the entire thing to the next statement?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer avoiding ternary operators altogether as a convention :) https://agiletribe.wordpress.com/2011/11/01/21-avoid-ternary-conditional-operator/
boolean exclusive = false;
if(type == Predicate.Type.IS_NULL) {
exclusive = true
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are different performance wise. This if condition is redundant.
Adding null predicate support in reference to Issue #4230
This PR adds limited support for "IS NULL" and "IS NOT NULL" filter predicates. Currently this only works for leaf filter predicates.