-
Notifications
You must be signed in to change notification settings - Fork 1k
PHOENIX-5072 Cursor Query Loops Eternally with Local Index, Returns F… #1287
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
Conversation
|
💔 -1 overall
This message was automatically generated. |
| throw new RowValueConstructorOffsetNotCoercibleException("No table or index could be coerced to the PK as the offset. Or an uncovered index was attempted"); | ||
| } | ||
|
|
||
| if (applicablePlans.get(0) instanceof CursorFetchPlan) { |
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 would rather put in a generic query method if possible. This code seems to imply that the cursor fetch plan is always first followed by several normal execution plans. This special case handling seems awkward at best is. it possible to generalize this somehow either in initial plan creation ie create them as separate cursor plans or maybe as part of a general plan method? I probably am missing a bunch of details.
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.
Thank you for the review @dbwong !
62f615c to
cd8c2e1
Compare
|
The ScanPlan in CursorFetchPlan was not using the index when we called the optimize on the CursorFetchPlan it added a simple ScanPlan (using the index) to the applicablePlans and at the and it got selected as the best one. phoenix/phoenix-core/src/main/java/org/apache/phoenix/optimize/QueryOptimizer.java Line 245 in 9dfb423
I've updated the constructor to optimize the ScanPlan at the first place. |
|
💔 -1 overall
This message was automatically generated. |
| try { | ||
| compilePlan = statement.getConnection().getQueryServices().getOptimizer().optimize(statement, queryPlan); | ||
| } catch (SQLException e) { | ||
| e.printStackTrace(); |
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.
Please use logger here.
| QueryPlan compilePlan = queryPlan; | ||
| try { | ||
| compilePlan = statement.getConnection().getQueryServices().getOptimizer().optimize(statement, queryPlan); | ||
| } catch (SQLException e) { |
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.
why do we want to handle the exception, shouldn't we just propogate?
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 wanted to handle the exception to minimise the effect of this change in case the optimize() throws an Exception.
Even if we handle the exception here (in the DeclareCursorCompiler) later optimize() will be called on the CursorFetchPlan and the Exception would be thrown there so it doesn't really makes sense to handle it here probably.
cd8c2e1 to
3e676f6
Compare
|
Thank you @ankitsinghal for the review. |
|
💔 -1 overall
This message was automatically generated. |
stoty
left a comment
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.
Some nits on the test.
phoenix-core/src/main/java/org/apache/phoenix/compile/DeclareCursorCompiler.java
Outdated
Show resolved
Hide resolved
phoenix-core/src/it/java/org/apache/phoenix/end2end/CursorWithRowValueConstructorIT.java
Outdated
Show resolved
Hide resolved
phoenix-core/src/it/java/org/apache/phoenix/end2end/CursorWithRowValueConstructorIT.java
Outdated
Show resolved
Hide resolved
phoenix-core/src/it/java/org/apache/phoenix/end2end/CursorWithRowValueConstructorIT.java
Outdated
Show resolved
Hide resolved
| this.statement = statement; | ||
| this.operation = operation; | ||
| this.queryPlan = queryPlan; | ||
| this.queryPlan = statement.getConnection().getQueryServices().getOptimizer() |
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.
How does this change help?
By pre-optimizing the query, we force the next optimization plan to be a No-Op ?
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.
With this change we optimize the plan inside the CursorFetchPlan.
Later when the next optimize is called, the original CursorFetchPlan will be selected as there won't be any better plans.
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.
Please add a code comment with this information and a reference to this ticket.
3e676f6 to
5934b95
Compare
|
💔 -1 overall
This message was automatically generated. |
5934b95 to
a13b255
Compare
stoty
left a comment
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.
+1 LGTM (but better check with @ankitsinghal too)
|
💔 -1 overall
This message was automatically generated. |
…ine Without It
I found out that when we had (local) index then we didn't have the CursorFetchPlan but it was optimized to a ScanPlan on the index.