[ 
https://issues.apache.org/jira/browse/HBASE-30351?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

ASF GitHub Bot updated HBASE-30351:
-----------------------------------
    Labels: pull-request-available  (was: )

> ROWS_SCANNED scan metric double-counts rows passing the filter when the scan 
> uses the joined heap (essential column family filtering)
> -------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HBASE-30351
>                 URL: https://issues.apache.org/jira/browse/HBASE-30351
>             Project: HBase
>          Issue Type: Bug
>          Components: metrics, Scanners
>    Affects Versions: 3.0.0, 4.0.0-alpha-1, 2.6.7
>            Reporter: Jeongmin Kim
>            Priority: Minor
>              Labels: pull-request-available
>
> When a scan enables {{Scan#setLoadColumnFamiliesOnDemand(true)}} and its 
> filter marks some column families as non-essential 
> ({{{}Filter#isFamilyEssential{}}}, introduced by HBASE-5416), 
> {{RegionScannerImpl}} populates a row in two steps: the essential families 
> through the store heap and — only if the row passes the filter — the 
> remaining families through the joined heap.
> Both steps go through {{{}RegionScannerImpl#populateResult{}}}, which 
> increments the ROWS_SCANNED metric 
> ({{{}ServerSideScanMetrics.COUNT_OF_ROWS_SCANNED_KEY_METRIC_NAME{}}}, 
> introduced by HBASE-5980) each time the given heap finishes the current row:
> {code:java}
> nextKv = heap.peek();
> moreCellsInRow = moreCellsInRow(nextKv, currentRowCell);
> if (!moreCellsInRow) {
> incrementCountOfRowsScannedMetric(scannerContext);
> } {code}
> There is no guard against the second call on the joined heap, so every row 
> that passes the filter and has data in a non-essential family is counted 
> twice — once when the store heap finishes the row and once more when the 
> joined heap finishes it. Rows rejected by the filter are counted once. The 
> reported value effectively becomes "rows scanned + rows returned", which 
> breaks the metric for its usual purposes (filter selectivity / scan 
> efficiency analysis, the MapReduce {{ROWS_SCANNED}} HBase counter, 
> comparisons against {{{}ROWS_FILTERED{}}}).
> Reproduction with stock filters only:
>  # Create a table with two column families, e.g. {{essential}} and 
> {{{}joined{}}}, and put a cell in both families for every row.
>  # Scan with {{{}setScanMetricsEnabled(true){}}}, 
> {{setLoadColumnFamiliesOnDemand(true)}} and a {{SingleColumnValueFilter}} on 
> family {{essential}} with {{setFilterIfMissing(true)}} (this makes the other 
> family non-essential via {{{}SingleColumnValueFilter#isFamilyEssential{}}}).
>  # With 10 rows of which 5 match the filter, ROWS_SCANNED reports 15 instead 
> of 10, while ROWS_FILTERED correctly reports 5. Without 
> {{setLoadColumnFamiliesOnDemand(true)}} the same scan reports 10.
> The double counting is invisible in the existing 
> {{TestServerSideScanMetricsFromClientSide}} because its table has a single 
> column family, so the joined heap is never exercised.
> Proposed fix: count a completed row in {{populateResult}} only when 
> populating from the store heap. The joined heap only re-populates rows that 
> already passed the filter, so the store heap completion is the single 
> canonical "row scanned" event (rows filtered by row key keep their separate 
> increment in {{{}nextInternal{}}}). A PR with the fix and a unit test in 
> {{TestServerSideScanMetricsFromClientSide}} follows.
> Verified on branch-2, branch-2.6, branch-3 and master (same code in 
> {{populateResult}} / {{{}populateFromJoinedHeap{}}}).



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to