HBASE-2823 Entire Row Deletes not stored in Row+Col Bloom
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@982472 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
37af9aab2e
commit
25ffbc5f11
|
@ -469,6 +469,8 @@ Release 0.21.0 - Unreleased
|
||||||
HBASE-2871 Make "start|stop" commands symmetric for Master & Cluster
|
HBASE-2871 Make "start|stop" commands symmetric for Master & Cluster
|
||||||
(Nicolas Spiegelberg via Stack)
|
(Nicolas Spiegelberg via Stack)
|
||||||
HBASE-2901 HBASE-2461 broke build
|
HBASE-2901 HBASE-2461 broke build
|
||||||
|
HBASE-2823 Entire Row Deletes not stored in Row+Col Bloom
|
||||||
|
(Alexander Georgiev via Stack)
|
||||||
|
|
||||||
IMPROVEMENTS
|
IMPROVEMENTS
|
||||||
HBASE-1760 Cleanup TODOs in HTable
|
HBASE-1760 Cleanup TODOs in HTable
|
||||||
|
|
|
@ -694,6 +694,13 @@ public class StoreFile {
|
||||||
|
|
||||||
if (bloomType != BloomType.NONE && conf != null) {
|
if (bloomType != BloomType.NONE && conf != null) {
|
||||||
float err = conf.getFloat(IO_STOREFILE_BLOOM_ERROR_RATE, (float)0.01);
|
float err = conf.getFloat(IO_STOREFILE_BLOOM_ERROR_RATE, (float)0.01);
|
||||||
|
// Since in row+col blooms we have 2 calls to shouldSeek() instead of 1
|
||||||
|
// and the false positives are adding up, we should keep the error rate
|
||||||
|
// twice as low in order to maintain the number of false positives as
|
||||||
|
// desired by the user
|
||||||
|
if (bloomType == BloomType.ROWCOL) {
|
||||||
|
err /= 2;
|
||||||
|
}
|
||||||
int maxFold = conf.getInt(IO_STOREFILE_BLOOM_MAX_FOLD, 7);
|
int maxFold = conf.getInt(IO_STOREFILE_BLOOM_MAX_FOLD, 7);
|
||||||
|
|
||||||
this.bloomFilter = new ByteBloomFilter(maxKeys, err,
|
this.bloomFilter = new ByteBloomFilter(maxKeys, err,
|
||||||
|
@ -800,7 +807,6 @@ public class StoreFile {
|
||||||
byte [] result = new byte[rl + ql];
|
byte [] result = new byte[rl + ql];
|
||||||
System.arraycopy(kv.getBuffer(), ro, result, 0, rl);
|
System.arraycopy(kv.getBuffer(), ro, result, 0, rl);
|
||||||
System.arraycopy(kv.getBuffer(), qo, result, rl, ql);
|
System.arraycopy(kv.getBuffer(), qo, result, rl, ql);
|
||||||
|
|
||||||
this.bloomFilter.add(result);
|
this.bloomFilter.add(result);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -943,8 +949,18 @@ public class StoreFile {
|
||||||
try {
|
try {
|
||||||
ByteBuffer bloom = reader.getMetaBlock(BLOOM_FILTER_DATA_KEY, true);
|
ByteBuffer bloom = reader.getMetaBlock(BLOOM_FILTER_DATA_KEY, true);
|
||||||
if (bloom != null) {
|
if (bloom != null) {
|
||||||
|
if (this.bloomFilterType == BloomType.ROWCOL) {
|
||||||
|
// Since a Row Delete is essentially a DeleteFamily applied to all
|
||||||
|
// columns, a file might be skipped if using row+col Bloom filter.
|
||||||
|
// In order to ensure this file is included an additional check is
|
||||||
|
// required looking only for a row bloom.
|
||||||
|
return this.bloomFilter.contains(key, bloom) ||
|
||||||
|
this.bloomFilter.contains(row, bloom);
|
||||||
|
}
|
||||||
|
else {
|
||||||
return this.bloomFilter.contains(key, bloom);
|
return this.bloomFilter.contains(key, bloom);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Error reading bloom filter data -- proceeding without",
|
LOG.error("Error reading bloom filter data -- proceeding without",
|
||||||
e);
|
e);
|
||||||
|
|
|
@ -2723,6 +2723,47 @@ public class TestHRegion extends HBaseTestCase {
|
||||||
checkOneCell(kvs[3], FAMILY, 0, 0, 1);
|
checkOneCell(kvs[3], FAMILY, 0, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Testcase to cover bug-fix for HBASE-2823
|
||||||
|
* Ensures correct delete when issuing delete row
|
||||||
|
* on columns with bloom filter set to row+col (BloomType.ROWCOL)
|
||||||
|
*/
|
||||||
|
public void testDeleteRowWithBloomFilter() throws IOException {
|
||||||
|
byte [] tableName = Bytes.toBytes("testDeleteRowWithBloomFilter");
|
||||||
|
byte [] familyName = Bytes.toBytes("familyName");
|
||||||
|
|
||||||
|
// Create Table
|
||||||
|
HColumnDescriptor hcd = new HColumnDescriptor(familyName, Integer.MAX_VALUE,
|
||||||
|
HColumnDescriptor.DEFAULT_COMPRESSION, false, true,
|
||||||
|
HColumnDescriptor.DEFAULT_TTL, "rowcol");
|
||||||
|
|
||||||
|
HTableDescriptor htd = new HTableDescriptor(tableName);
|
||||||
|
htd.addFamily(hcd);
|
||||||
|
HRegionInfo info = new HRegionInfo(htd, null, null, false);
|
||||||
|
Path path = new Path(DIR + "TestDeleteRowWithBloomFilter");
|
||||||
|
region = HRegion.createHRegion(info, path, conf);
|
||||||
|
|
||||||
|
// Insert some data
|
||||||
|
byte row[] = Bytes.toBytes("row1");
|
||||||
|
byte col[] = Bytes.toBytes("col1");
|
||||||
|
|
||||||
|
Put put = new Put(row);
|
||||||
|
put.add(familyName, col, 1, Bytes.toBytes("SomeRandomValue"));
|
||||||
|
region.put(put);
|
||||||
|
region.flushcache();
|
||||||
|
|
||||||
|
Delete del = new Delete(row);
|
||||||
|
region.delete(del, null, true);
|
||||||
|
region.flushcache();
|
||||||
|
|
||||||
|
// Get remaining rows (should have none)
|
||||||
|
Get get = new Get(row);
|
||||||
|
get.addColumn(familyName, col);
|
||||||
|
|
||||||
|
KeyValue[] keyValues = region.get(get, null).raw();
|
||||||
|
assertTrue(keyValues.length == 0);
|
||||||
|
}
|
||||||
|
|
||||||
private void putData(int startRow, int numRows, byte [] qf,
|
private void putData(int startRow, int numRows, byte [] qf,
|
||||||
byte [] ...families)
|
byte [] ...families)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
Loading…
Reference in New Issue