Index: src/java/org/apache/hadoop/hbase/HConstants.java =================================================================== --- src/java/org/apache/hadoop/hbase/HConstants.java (revision 894322) +++ src/java/org/apache/hadoop/hbase/HConstants.java (working copy) @@ -284,4 +284,12 @@ TABLE_SET_HTD, TABLE_SPLIT } + + /** + * Maximum number of bytes returned when calling a scanner's next method. + * Note that when a single row is larger than this limit the row is still + * returned completely. + */ + public static long MAXIMUM_SCANNER_RESULT_SIZE = 1024 * 1024; + } Index: src/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java =================================================================== --- src/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (revision 894322) +++ src/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (working copy) @@ -1878,12 +1878,16 @@ } this.leases.renewLease(scannerName); List results = new ArrayList(); - for (int i = 0; i < nbRows; i++) { + long currentScanResultSize = 0; + for (int i = 0; i < nbRows && currentScanResultSize < MAXIMUM_SCANNER_RESULT_SIZE; i++) { requestCount.incrementAndGet(); // Collect values to be returned here List values = new ArrayList(); boolean moreRows = s.next(values); if (!values.isEmpty()) { + for (KeyValue kv : values) { + currentScanResultSize += kv.heapSize(); + } results.add(new Result(values)); } if (!moreRows) { Index: src/java/org/apache/hadoop/hbase/client/HTable.java =================================================================== --- src/java/org/apache/hadoop/hbase/client/HTable.java (revision 894322) +++ src/java/org/apache/hadoop/hbase/client/HTable.java (working copy) @@ -1954,6 +1954,7 @@ } if (cache.size() == 0) { Result [] values = null; + long remainingResultSize = HConstants.MAXIMUM_SCANNER_RESULT_SIZE; int countdown = this.caching; // We need to reset it if it's a new callable that was created // with a countdown in nextScanner @@ -2001,12 +2002,15 @@ if (values != null && values.length > 0) { for (Result rs : values) { cache.add(rs); + for (KeyValue kv : rs.raw()) { + remainingResultSize -= kv.heapSize(); + } countdown--; this.lastResult = rs; } } // Values == null means server-side filter has determined we must STOP - } while (countdown > 0 && nextScanner(countdown, values == null)); + } while (remainingResultSize > 0 && countdown > 0 && nextScanner(countdown, values == null)); } if (cache.size() > 0) {