HBASE-4585 Avoid seek operation when current kv is deleted(Liyin Tang)

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1185771 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
ramkrishna 2011-10-18 17:52:06 +00:00
parent 712bf529b8
commit 9e071332b2
6 changed files with 57 additions and 36 deletions

View File

@ -625,6 +625,7 @@ Release 0.92.0 - Unreleased
HBASE-4568 Make zk dump jsp response faster HBASE-4568 Make zk dump jsp response faster
HBASE-4606 Remove spam in HCM and fix a list.size == 0 HBASE-4606 Remove spam in HCM and fix a list.size == 0
HBASE-3581 hbase rpc should send size of response HBASE-3581 hbase rpc should send size of response
HBASE-4585 Avoid seek operation when current kv is deleted(Liyin Tang)
TASKS TASKS

View File

@ -51,9 +51,9 @@ public interface DeleteTracker {
* @param qualifierOffset column qualifier offset * @param qualifierOffset column qualifier offset
* @param qualifierLength column qualifier length * @param qualifierLength column qualifier length
* @param timestamp timestamp * @param timestamp timestamp
* @return true is the specified KeyValue is deleted, false if not * @return deleteResult The result tells whether the KeyValue is deleted and why
*/ */
public boolean isDeleted(byte [] buffer, int qualifierOffset, public DeleteResult isDeleted(byte [] buffer, int qualifierOffset,
int qualifierLength, long timestamp); int qualifierLength, long timestamp);
/** /**
@ -94,4 +94,17 @@ public interface DeleteTracker {
NEXT_NEW NEXT_NEW
} }
/**
* Returns codes for delete result.
* The codes tell the ScanQueryMatcher whether the kv is deleted and why.
* Based on the delete result, the ScanQueryMatcher will decide the next
* operation
*/
public static enum DeleteResult {
FAMILY_DELETED, // The KeyValue is deleted by a delete family.
COLUMN_DELETED, // The KeyValue is deleted by a delete column.
VERSION_DELETED, // The KeyValue is deleted by a version delete.
NOT_DELETED
}
} }

View File

@ -21,6 +21,7 @@
package org.apache.hadoop.hbase.regionserver; package org.apache.hadoop.hbase.regionserver;
import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.regionserver.DeleteTracker.DeleteResult;
import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Bytes;
/** /**
@ -99,13 +100,13 @@ public class ScanDeleteTracker implements DeleteTracker {
* @param qualifierOffset column qualifier offset * @param qualifierOffset column qualifier offset
* @param qualifierLength column qualifier length * @param qualifierLength column qualifier length
* @param timestamp timestamp * @param timestamp timestamp
* @return true is the specified KeyValue is deleted, false if not * @return deleteResult
*/ */
@Override @Override
public boolean isDeleted(byte [] buffer, int qualifierOffset, public DeleteResult isDeleted(byte [] buffer, int qualifierOffset,
int qualifierLength, long timestamp) { int qualifierLength, long timestamp) {
if (timestamp <= familyStamp) { if (timestamp <= familyStamp) {
return true; return DeleteResult.FAMILY_DELETED;
} }
if (deleteBuffer != null) { if (deleteBuffer != null) {
@ -114,12 +115,12 @@ public class ScanDeleteTracker implements DeleteTracker {
if (ret == 0) { if (ret == 0) {
if (deleteType == KeyValue.Type.DeleteColumn.getCode()) { if (deleteType == KeyValue.Type.DeleteColumn.getCode()) {
return true; return DeleteResult.COLUMN_DELETED;
} }
// Delete (aka DeleteVersion) // Delete (aka DeleteVersion)
// If the timestamp is the same, keep this one // If the timestamp is the same, keep this one
if (timestamp == deleteTimestamp) { if (timestamp == deleteTimestamp) {
return true; return DeleteResult.VERSION_DELETED;
} }
// use assert or not? // use assert or not?
assert timestamp < deleteTimestamp; assert timestamp < deleteTimestamp;
@ -138,7 +139,7 @@ public class ScanDeleteTracker implements DeleteTracker {
} }
} }
return false; return DeleteResult.NOT_DELETED;
} }
@Override @Override
@ -158,4 +159,4 @@ public class ScanDeleteTracker implements DeleteTracker {
public void update() { public void update() {
this.reset(); this.reset();
} }
} }

View File

@ -26,6 +26,7 @@ import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.filter.Filter; import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.Filter.ReturnCode; import org.apache.hadoop.hbase.filter.Filter.ReturnCode;
import org.apache.hadoop.hbase.io.TimeRange; import org.apache.hadoop.hbase.io.TimeRange;
import org.apache.hadoop.hbase.regionserver.DeleteTracker.DeleteResult;
import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Bytes;
import java.io.IOException; import java.io.IOException;
@ -184,15 +185,20 @@ public class ScanQueryMatcher {
} }
} }
if (!this.deletes.isEmpty() && if (!this.deletes.isEmpty()) {
deletes.isDeleted(bytes, offset, qualLength, timestamp)) { DeleteResult deleteResult = deletes.isDeleted(bytes, offset, qualLength,
timestamp);
// May be able to optimize the SKIP here, if we matched switch (deleteResult) {
// due to a DelFam, we can skip to next row case FAMILY_DELETED:
// due to a DelCol, we can skip to next col case COLUMN_DELETED:
// But it requires more info out of isDelete(). return columns.getNextRowOrNextColumn(bytes, offset, qualLength);
// needful -> million column challenge. case VERSION_DELETED:
return MatchCode.SKIP; return MatchCode.SKIP;
case NOT_DELETED:
break;
default:
throw new RuntimeException("UNEXPECTED");
}
} }
int timestampComparison = tr.compare(timestamp); int timestampComparison = tr.compare(timestamp);

View File

@ -283,14 +283,14 @@ public class TestBlocksRead extends HBaseTestCase {
deleteFamily(FAMILY, "row", 6); deleteFamily(FAMILY, "row", 6);
region.flushcache(); region.flushcache();
// Baseline expected blocks read: 6. // Baseline expected blocks read: 4. [HBASE-4585]
kvs = getData(FAMILY, "row", "col1", 6); kvs = getData(FAMILY, "row", "col1", 4);
assertEquals(0, kvs.length); assertEquals(0, kvs.length);
kvs = getData(FAMILY, "row", "col2", 6); kvs = getData(FAMILY, "row", "col2", 5);
assertEquals(0, kvs.length); assertEquals(0, kvs.length);
kvs = getData(FAMILY, "row", "col3", 6); kvs = getData(FAMILY, "row", "col3", 4);
assertEquals(0, kvs.length); assertEquals(0, kvs.length);
kvs = getData(FAMILY, "row", Arrays.asList("col1", "col2", "col3"), 6); kvs = getData(FAMILY, "row", Arrays.asList("col1", "col2", "col3"), 5);
assertEquals(0, kvs.length); assertEquals(0, kvs.length);
// File 5: Delete // File 5: Delete
@ -304,8 +304,8 @@ public class TestBlocksRead extends HBaseTestCase {
putData(FAMILY, "row", "col3", 9); putData(FAMILY, "row", "col3", 9);
region.flushcache(); region.flushcache();
// Baseline expected blocks read: 10 // Baseline expected blocks read: 8. [HBASE-4585]
kvs = getData(FAMILY, "row", Arrays.asList("col1", "col2", "col3"), 10); kvs = getData(FAMILY, "row", Arrays.asList("col1", "col2", "col3"), 8);
assertEquals(0, kvs.length); assertEquals(0, kvs.length);
// File 7: Put back new data // File 7: Put back new data

View File

@ -23,6 +23,7 @@ package org.apache.hadoop.hbase.regionserver;
import org.apache.hadoop.hbase.HBaseTestCase; import org.apache.hadoop.hbase.HBaseTestCase;
import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.regionserver.DeleteTracker.DeleteResult;
import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Bytes;
@ -42,8 +43,8 @@ public class TestScanDeleteTracker extends HBaseTestCase {
deleteType = KeyValue.Type.Delete.getCode(); deleteType = KeyValue.Type.Delete.getCode();
sdt.add(qualifier, 0, qualifier.length, timestamp, deleteType); sdt.add(qualifier, 0, qualifier.length, timestamp, deleteType);
boolean ret = sdt.isDeleted(qualifier, 0, qualifier.length, timestamp); DeleteResult ret = sdt.isDeleted(qualifier, 0, qualifier.length, timestamp);
assertEquals(true, ret); assertEquals(DeleteResult.VERSION_DELETED, ret);
} }
public void testDeletedBy_DeleteColumn() { public void testDeletedBy_DeleteColumn() {
@ -52,8 +53,8 @@ public class TestScanDeleteTracker extends HBaseTestCase {
sdt.add(qualifier, 0, qualifier.length, timestamp, deleteType); sdt.add(qualifier, 0, qualifier.length, timestamp, deleteType);
timestamp -= 5; timestamp -= 5;
boolean ret = sdt.isDeleted(qualifier, 0, qualifier.length, timestamp); DeleteResult ret = sdt.isDeleted(qualifier, 0, qualifier.length, timestamp);
assertEquals(true, ret); assertEquals(DeleteResult.COLUMN_DELETED, ret);
} }
public void testDeletedBy_DeleteFamily() { public void testDeletedBy_DeleteFamily() {
@ -63,8 +64,8 @@ public class TestScanDeleteTracker extends HBaseTestCase {
sdt.add(qualifier, 0, qualifier.length, timestamp, deleteType); sdt.add(qualifier, 0, qualifier.length, timestamp, deleteType);
timestamp -= 5; timestamp -= 5;
boolean ret = sdt.isDeleted(qualifier, 0, qualifier.length, timestamp); DeleteResult ret = sdt.isDeleted(qualifier, 0, qualifier.length, timestamp);
assertEquals(true, ret); assertEquals(DeleteResult.FAMILY_DELETED, ret);
} }
public void testDelete_DeleteColumn() { public void testDelete_DeleteColumn() {
@ -78,8 +79,8 @@ public class TestScanDeleteTracker extends HBaseTestCase {
sdt.add(qualifier, 0, qualifier.length, timestamp, deleteType); sdt.add(qualifier, 0, qualifier.length, timestamp, deleteType);
timestamp -= 5; timestamp -= 5;
boolean ret = sdt.isDeleted(qualifier, 0, qualifier.length, timestamp); DeleteResult ret = sdt.isDeleted(qualifier, 0, qualifier.length, timestamp);
assertEquals(true, ret); assertEquals(DeleteResult.COLUMN_DELETED, ret);
} }
@ -93,8 +94,8 @@ public class TestScanDeleteTracker extends HBaseTestCase {
deleteType = KeyValue.Type.Delete.getCode(); deleteType = KeyValue.Type.Delete.getCode();
sdt.add(qualifier, 0, qualifier.length, timestamp, deleteType); sdt.add(qualifier, 0, qualifier.length, timestamp, deleteType);
boolean ret = sdt.isDeleted(qualifier, 0, qualifier.length, timestamp); DeleteResult ret = sdt.isDeleted(qualifier, 0, qualifier.length, timestamp);
assertEquals(true, ret); assertEquals( DeleteResult.VERSION_DELETED, ret);
} }
//Testing new way where we save the Delete in case of a Delete for specific //Testing new way where we save the Delete in case of a Delete for specific
@ -109,5 +110,4 @@ public class TestScanDeleteTracker extends HBaseTestCase {
assertEquals(false ,sdt.isEmpty()); assertEquals(false ,sdt.isEmpty());
} }
} }