@Test
  public void testLazySeekBlocksRead() throws Exception {
    byte[] TABLE = Bytes.toBytes("testLazySeekBlocksRead");
    String FAMILY = "cf1";
    Cell[] kvs;
    this.region = initHRegion(TABLE, testName.getMethodName(), conf, FAMILY);

    try {
      // File 1
      putData(FAMILY, "row", "col1", 1);
      putData(FAMILY, "row", "col2", 2);
      region.flush(true);

      // File 2
      putData(FAMILY, "row", "col1", 3);
      putData(FAMILY, "row", "col2", 4);
      region.flush(true);

      // Expected blocks read: 1.
      // File 2's top block is also the KV we are
      // interested. So only 1 seek is needed.
      kvs = getData(FAMILY, "row", Arrays.asList("col1"), 1);
      assertEquals(1, kvs.length);
      verifyData(kvs[0], "row", "col1", 3);

      // Expected blocks read: 2
      // File 2's top block has the "col1" KV we are
      // interested. We also need "col2" which is in a block
      // of its own. So, we need that block as well.
      kvs = getData(FAMILY, "row", Arrays.asList("col1", "col2"), 2);
      assertEquals(2, kvs.length);
      verifyData(kvs[0], "row", "col1", 3);
      verifyData(kvs[1], "row", "col2", 4);

      // File 3: Add another column
      putData(FAMILY, "row", "col3", 5);
      region.flush(true);

      // Expected blocks read: 1
      // File 3's top block has the "col3" KV we are
      // interested. So only 1 seek is needed.
      kvs = getData(FAMILY, "row", "col3", 1);
      assertEquals(1, kvs.length);
      verifyData(kvs[0], "row", "col3", 5);

      // Get a column from older file.
      // For ROWCOL Bloom filter: Expected blocks read: 1.
      // For ROW Bloom filter: Expected blocks read: 2.
      // For NONE Bloom filter: Expected blocks read: 2.
      kvs = getData(FAMILY, "row", Arrays.asList("col1"), 1, 2, 2);
      assertEquals(1, kvs.length);
      verifyData(kvs[0], "row", "col1", 3);

      // File 4: Delete the entire row.
      deleteFamily(FAMILY, "row", 6);
      region.flush(true);

      // For ROWCOL Bloom filter: Expected blocks read: 2.
      // For ROW Bloom filter: Expected blocks read: 3.
      // For NONE Bloom filter: Expected blocks read: 3.
      kvs = getData(FAMILY, "row", "col1", 2, 3, 3);
      assertEquals(0, kvs.length);
      kvs = getData(FAMILY, "row", "col2", 2, 3, 3);
      assertEquals(0, kvs.length);
      kvs = getData(FAMILY, "row", "col3", 2);
      assertEquals(0, kvs.length);
      kvs = getData(FAMILY, "row", Arrays.asList("col1", "col2", "col3"), 4);
      assertEquals(0, kvs.length);

      // File 5: Delete
      deleteFamily(FAMILY, "row", 10);
      region.flush(true);

      // File 6: some more puts, but with timestamps older than the
      // previous delete.
      putData(FAMILY, "row", "col1", 7);
      putData(FAMILY, "row", "col2", 8);
      putData(FAMILY, "row", "col3", 9);
      region.flush(true);

      // Baseline expected blocks read: 6. [HBASE-4532]
      kvs = getData(FAMILY, "row", Arrays.asList("col1", "col2", "col3"), 6, 7, 7);
      assertEquals(0, kvs.length);

      // File 7: Put back new data
      putData(FAMILY, "row", "col1", 11);
      putData(FAMILY, "row", "col2", 12);
      putData(FAMILY, "row", "col3", 13);
      region.flush(true);

      // Expected blocks read: 8. [HBASE-4585, HBASE-13109]
      kvs = getData(FAMILY, "row", Arrays.asList("col1", "col2", "col3"), 8, 9, 9);
      assertEquals(3, kvs.length);
      verifyData(kvs[0], "row", "col1", 11);
      verifyData(kvs[1], "row", "col2", 12);
      verifyData(kvs[2], "row", "col3", 13);
    } finally {
      HBaseTestingUtil.closeRegionAndWAL(this.region);
      this.region = null;
    }
  }
Test # of blocks read (targeted at some of the cases Lazy Seek optimizes).
hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestBlocksRead.java