Repository navigation
HIVE-24203: Implement stats annotation rule for the LateralViewJoinOperator - #1531
Conversation
| @@ -0,0 +1,38 @@ | |||
| set hive.fetch.task.conversion=none; | |||
There was a problem hiding this comment.
To make EXPLAIN show Statistics. I'm thinking to create another ticket and add this line to other annotate_stats_*.q.
| } | ||
|
|
||
| /** | ||
| * LateralViewJoinOperator joins the output of select with the output of UDTF. |
There was a problem hiding this comment.
Could you provide a bit more details about what the rule does? Most of the other rules in this class give a general overview of the cost model they implement.
There was a problem hiding this comment.
@zabetak Thanks for taking a look!
I added a description. Please feel free to ask me if something doesn't make sense.
b37a00a to
e2479f8
Compare
| * | ||
| * For each row of the source, the left branch just picks columns and the right branch processes UDTF. | ||
| * And then LVJ joins a row from the left branch with rows from the right branch. | ||
| * The join has one-to-many relationship since UDTF can generate multiple rows. |
There was a problem hiding this comment.
Just leaving a note. I took a quick look at the UDTF logic and it seems the selectivity is hardcoded via config. It seems the outer flag is not taken into account either, which could be a straightforward improvement for the estimates, i.e., UDFT will produce at least as many rows as it receives.
| return null; | ||
| } | ||
|
|
||
| final Statistics selectStats = parents.get(LateralViewJoinOperator.SELECT_TAG).getStatistics().clone(); |
There was a problem hiding this comment.
Do you need to clone them? Are you modifying them? (Same for next line)
There was a problem hiding this comment.
As for udtfStats, we can totally avoid clone.
As for udtfStats, its column stats will be updated. However, looks like StatsUtils.getColStatisticsFromExprMap clones them?
Anyway I think we can remove them if CI passes. I will try it.
There was a problem hiding this comment.
Nothing was not unexpectedly broken. CI failed but it would not be related to this PR...
| Lateral View Join Operator | ||
| outputColumnNames: _col0, _col1, _col5, _col6 | ||
| Statistics: Num rows: 0 Data size: 24 Basic stats: PARTIAL Column stats: NONE | ||
| Statistics: Num rows: 0 Data size: 24 Basic stats: PARTIAL Column stats: COMPLETE |
There was a problem hiding this comment.
With clone, the following condition is not satisfied since the basic stats of parent operators are PARTIAL.
There was a problem hiding this comment.
BTW, it would be better that the UDTF rule puts one in num rows in case that it becomes zero.
There was a problem hiding this comment.
definetly - I don't think it will be 0 in reality!
There was a problem hiding this comment.
This is an edge case since HIVE_STATS_UDTF_FACTOR is greater than or equal to 1. Anyway, I created a ticket.
https://issues.apache.org/jira/browse/HIVE-24240
| final Statistics selectStats = parents.get(LateralViewJoinOperator.SELECT_TAG).getStatistics(); | ||
| final Statistics udtfStats = parents.get(LateralViewJoinOperator.UDTF_TAG).getStatistics(); | ||
|
|
||
| final double factor = (double) udtfStats.getNumRows() / (double) selectStats.getNumRows(); |
There was a problem hiding this comment.
I know selectStats.getNumRows() should not be zero - but just in case... could you also add the resulting logic as StatsUtils or something like that?
There was a problem hiding this comment.
Added steps to check both numbers and ensure at least one record on stats.
5039634
| joinedStats = applyRuntimeStats(aspCtx.getParseContext().getContext(), joinedStats, lop); | ||
| lop.setStatistics(joinedStats); | ||
|
|
||
| if (LOG.isDebugEnabled()) { | ||
| LOG.debug("[0] STATS-" + lop.toString() + ": " + joinedStats.extendedToString()); | ||
| } |
There was a problem hiding this comment.
this seems to be a common expression in both branches of the if - could you move it outside?
There was a problem hiding this comment.
I wonder if we should switch [0] or [1] based on a condition. I can see some rules use a different marker based on maybe the existence of column stats.
There was a problem hiding this comment.
I don't know what's the point of these [0]/[1] markers; from one of the historical commits it seems to me like these are some kind of "log message indexes" inside the method ....
I think we could stop doing that...
| colStats.setNumNulls(StatsUtils.safeMult(colStats.getNumNulls(), factor)); | ||
| // When factor > 1, the same records are duplicated and countDistinct never changes. | ||
| if (factor < 1.0) { | ||
| colStats.setCountDistint(StatsUtils.safeMult(colStats.getCountDistint(), factor)); |
There was a problem hiding this comment.
I think we should make sure that NDV is at least 1 in case numrows is >0
There was a problem hiding this comment.
Now I think this is available for this purpose if we add updating num trues and num falses?
hive/ql/src/java/org/apache/hadoop/hive/ql/stats/StatsUtils.java
Lines 2050 to 2100 in c082a72
There was a problem hiding this comment.
This method may include additional logging and logics to optimize JOIN such as cs.setFilterColumn. It would be better to implement a simple and separate utility.
There was a problem hiding this comment.
Ceiled. I moved this method since I'd like to reuse it for HIVE-24240.
5039634
| Lateral View Join Operator | ||
| outputColumnNames: _col0, _col1, _col5, _col6 | ||
| Statistics: Num rows: 0 Data size: 24 Basic stats: PARTIAL Column stats: NONE | ||
| Statistics: Num rows: 0 Data size: 24 Basic stats: PARTIAL Column stats: COMPLETE |
There was a problem hiding this comment.
definetly - I don't think it will be 0 in reality!
|
|
||
| final double factor = (double) udtfStats.getNumRows() / (double) selectStats.getNumRows(); | ||
| final long udtfNumRows = Math.max(udtfStats.getNumRows(), 1); | ||
| final double factor = (double) udtfNumRows / (double) Math.max(selectStats.getNumRows(), 1); |
There was a problem hiding this comment.
factor will be greater than 0.0 and must not 0 or infinity.
|
@kgyrtkirk I have updated some points so that # of rows will never be 0. |
|
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
What changes were proposed in this pull request?
Estimate statistics of LATERAL VIEW correctly.
StatsRulesProcFactory doesn't have any rules to handle a JOIN by LATERAL VIEW.
This can cause an underestimation in case that UDTF in LATERAL VIEW generates multiple rows.
Why are the changes needed?
Significant underestimation can happen when LATERAL VIEW increases the number of records a lot and the source table has large.
Does this PR introduce any user-facing change?
No.
How was this patch tested?
Added one test case.