phoenix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jamestay...@apache.org
Subject [2/2] phoenix git commit: PHOENIX-2143 Use guidepost bytes instead of region name in stats primary key (Ankit Singhal)
Date Thu, 14 Jan 2016 20:00:21 GMT
PHOENIX-2143 Use guidepost bytes instead of region name in stats primary key (Ankit Singhal)


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/3e740cbc
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/3e740cbc
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/3e740cbc

Branch: refs/heads/4.x-HBase-1.0
Commit: 3e740cbc504a9d2e8b9d26adbdb11ad2ba7018f2
Parents: d4fe704
Author: James Taylor <jtaylor@salesforce.com>
Authored: Thu Jan 14 11:59:12 2016 -0800
Committer: James Taylor <jtaylor@salesforce.com>
Committed: Thu Jan 14 11:59:12 2016 -0800

----------------------------------------------------------------------
 .../phoenix/end2end/StatsCollectorIT.java       |  26 ++-
 .../StatsCollectorWithSplitsAndMultiCFIT.java   | 186 ++-------------
 .../phoenix/coprocessor/MetaDataProtocol.java   |   2 +-
 .../UngroupedAggregateRegionObserver.java       |  61 +----
 .../phoenix/jdbc/PhoenixDatabaseMetaData.java   |  11 +-
 .../query/ConnectionQueryServicesImpl.java      |  78 +++++++
 .../apache/phoenix/query/QueryConstants.java    |  16 +-
 .../apache/phoenix/schema/MetaDataClient.java   |   3 +-
 .../phoenix/schema/stats/GuidePostsInfo.java    |  95 +-------
 .../schema/stats/StatisticsCollector.java       | 162 +++++--------
 .../phoenix/schema/stats/StatisticsScanner.java |  22 +-
 .../phoenix/schema/stats/StatisticsUtil.java    | 177 ++++++++------
 .../phoenix/schema/stats/StatisticsWriter.java  | 230 +++++++------------
 .../org/apache/phoenix/util/MetaDataUtil.java   |  35 +--
 .../java/org/apache/phoenix/util/ScanUtil.java  |   8 +
 15 files changed, 429 insertions(+), 683 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/3e740cbc/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorIT.java
index 5e048c5..954ad99 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorIT.java
@@ -110,7 +110,31 @@ public class StatsCollectorIT extends StatsCollectorAbstractIT {
         rs = conn.createStatement().executeQuery("SELECT k FROM " + tableName);
         assertTrue(rs.next());
         conn.close();
-	}
+    }
+
+    @Test
+    public void testNoDuplicatesAfterUpdateStats() throws Throwable {
+        Connection conn;
+        PreparedStatement stmt;
+        ResultSet rs;
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        conn = DriverManager.getConnection(getUrl(), props);
+        conn.createStatement()
+                .execute("CREATE TABLE x ( k VARCHAR, c1.a bigint,c2.b bigint CONSTRAINT pk PRIMARY KEY (k)) \n");
+        conn.createStatement().execute("upsert into x values ('abc',1,3)");
+        conn.createStatement().execute("upsert into x values ('def',2,4)");
+        conn.commit();
+        // CAll the update statistics query here
+        stmt = conn.prepareStatement("UPDATE STATISTICS X");
+        stmt.execute();
+        rs = conn.createStatement().executeQuery("SELECT k FROM x");
+        assertTrue(rs.next());
+        assertEquals("abc", rs.getString(1));
+        assertTrue(rs.next());
+        assertEquals("def", rs.getString(1));
+        assertTrue(!rs.next());
+        conn.close();
+    }
 
     @Test
     public void testUpdateStatsWithMultipleTables() throws Throwable {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/3e740cbc/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorWithSplitsAndMultiCFIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorWithSplitsAndMultiCFIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorWithSplitsAndMultiCFIT.java
index 6191a4f..dfe8b60 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorWithSplitsAndMultiCFIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StatsCollectorWithSplitsAndMultiCFIT.java
@@ -20,26 +20,22 @@ package org.apache.phoenix.end2end;
 import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
 import static org.apache.phoenix.util.TestUtil.getAllSplits;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
-import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 
-import org.apache.hadoop.hbase.HColumnDescriptor;
 import org.apache.hadoop.hbase.HRegionLocation;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.phoenix.jdbc.PhoenixConnection;
 import org.apache.phoenix.query.ConnectionQueryServices;
 import org.apache.phoenix.query.KeyRange;
 import org.apache.phoenix.query.QueryServices;
-import org.apache.phoenix.schema.stats.GuidePostsInfo;
 import org.apache.phoenix.util.PropertiesUtil;
 import org.apache.phoenix.util.QueryUtil;
 import org.apache.phoenix.util.ReadOnlyProps;
@@ -70,9 +66,8 @@ public class StatsCollectorWithSplitsAndMultiCFIT extends StatsCollectorAbstract
         PreparedStatement stmt;
         Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
         conn = DriverManager.getConnection(getUrl(), props);
-        conn.createStatement().execute(
-                "CREATE TABLE " + STATS_TEST_TABLE_NAME_NEW
-                        + "(k VARCHAR PRIMARY KEY, a.v INTEGER, b.v INTEGER, c.v INTEGER NULL, d.v INTEGER NULL) ");
+        conn.createStatement().execute("CREATE TABLE " + STATS_TEST_TABLE_NAME_NEW
+                + "(k VARCHAR PRIMARY KEY, a.v INTEGER, b.v INTEGER, c.v INTEGER NULL, d.v INTEGER NULL) ");
         stmt = conn.prepareStatement("UPSERT INTO " + STATS_TEST_TABLE_NAME_NEW + " VALUES(?,?, ?, ?, ?)");
         byte[] val = new byte[250];
         for (int i = 0; i < nRows; i++) {
@@ -105,173 +100,42 @@ public class StatsCollectorWithSplitsAndMultiCFIT extends StatsCollectorAbstract
         List<HRegionLocation> regions = services.getAllTableRegions(STATS_TEST_TABLE_NEW_BYTES);
         assertEquals(1, regions.size());
 
-        rs =
-                conn.createStatement()
-                        .executeQuery(
-                            "SELECT GUIDE_POSTS_COUNT, REGION_NAME, GUIDE_POSTS_ROW_COUNT, " +
-                            "MIN_KEY FROM SYSTEM.STATS WHERE PHYSICAL_NAME='"
-                                    + STATS_TEST_TABLE_NAME_NEW + "' AND REGION_NAME IS NOT NULL");
-        assertTrue(rs.next());
-        assertEquals(11, (rs.getLong(1)));
-        assertEquals(regions.get(0).getRegionInfo().getRegionNameAsString(), rs.getString(2));
-        // I get 25 here because for A there is an entry added with the default col
-        assertEquals(25, rs.getLong(3));
-        assertTrue(rs.next());
-        assertEquals(5, (rs.getLong(1)));
-        assertEquals(regions.get(0).getRegionInfo().getRegionNameAsString(), rs.getString(2));
-        // for b the count is lesser by 5
-        assertEquals(20, rs.getLong(3));
-        assertTrue(rs.next());
-        assertEquals(6, (rs.getLong(1)));
-        assertEquals(regions.get(0).getRegionInfo().getRegionNameAsString(), rs.getString(2));
-        assertEquals(25, rs.getLong(3));
-        assertTrue(rs.next());
-        assertEquals(6, (rs.getLong(1)));
-        assertEquals(regions.get(0).getRegionInfo().getRegionNameAsString(), rs.getString(2));
-        assertEquals(25, rs.getLong(3));
-        assertFalse(rs.next());
-        Collection<GuidePostsInfo> infos = TestUtil.getGuidePostsList(conn, STATS_TEST_TABLE_NAME_NEW);
-        long[] rowCountArr = new long[]{25, 20, 25, 25};
-        // CF A alone has double the bytecount because it has column qualifier A and column qualifier _0
-        long[] byteCountArr = new long[]{12144, 5540, 6652, 6652};
-        int i = 0;
-        for(GuidePostsInfo info : infos) {
-            assertRowCountAndByteCount(info, rowCountArr[i], byteCountArr[i]);
-            i++;
-        }
-        
         TestUtil.analyzeTable(conn, STATS_TEST_TABLE_NAME_NEW);
-        String query = "UPDATE STATISTICS " + STATS_TEST_TABLE_NAME_NEW + " SET \"" + QueryServices.STATS_GUIDEPOST_WIDTH_BYTES_ATTRIB + "\"=" + Long.toString(2000);
+        String query = "UPDATE STATISTICS " + STATS_TEST_TABLE_NAME_NEW + " SET \""
+                + QueryServices.STATS_GUIDEPOST_WIDTH_BYTES_ATTRIB + "\"=" + Long.toString(2000);
         conn.createStatement().execute(query);
         keyRanges = getAllSplits(conn, STATS_TEST_TABLE_NAME_NEW);
         assertEquals(6, keyRanges.size());
-    }
-
-    protected void assertRowCountAndByteCount(GuidePostsInfo info, long rowCount, long byteCount) {
-        assertEquals("Row count does not match ", rowCount, info.getRowCount());
-        assertEquals("Byte count does not match ", byteCount, info.getByteCount());
-    }
-
-    @Test
-    public void testSplitUpdatesStats() throws Exception {
-        int nRows = 20;
-        Connection conn;
-        PreparedStatement stmt;
-        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
-        conn = DriverManager.getConnection(getUrl(), props);
-        conn.createStatement().execute(
-                "CREATE TABLE " + STATS_TEST_TABLE_NAME + "(k VARCHAR PRIMARY KEY, v INTEGER) "
-                        + HColumnDescriptor.KEEP_DELETED_CELLS + "=" + Boolean.FALSE);
-        stmt = conn.prepareStatement("UPSERT INTO " + STATS_TEST_TABLE_NAME + " VALUES(?,?)");
-        byte[] val = new byte[250];
-        for (int i = 0; i < nRows; i++) {
-            stmt.setString(1, Character.toString((char)('a' + i)) + Bytes.toString(val));
-            stmt.setInt(2, i);
-            stmt.executeUpdate();
-        }
-        conn.commit();
-
-        ResultSet rs;
-        TestUtil.analyzeTable(conn, STATS_TEST_TABLE_NAME);
-        Collection<GuidePostsInfo> infos = TestUtil.getGuidePostsList(conn, STATS_TEST_TABLE_NAME);
-        for (GuidePostsInfo info : infos) {
-            assertEquals(20, info.getRowCount());
-            assertEquals(11040, info.getByteCount());
-            break;
-        }
-        List<KeyRange> keyRanges = getAllSplits(conn, STATS_TEST_TABLE_NAME);
-        assertEquals((nRows / 2) + 1, keyRanges.size());
-        rs = conn.createStatement().executeQuery("EXPLAIN SELECT * FROM " + STATS_TEST_TABLE_NAME);
-        assertEquals("CLIENT " + ((nRows / 2) + 1) + "-CHUNK " + "PARALLEL 1-WAY FULL SCAN OVER "
-                + STATS_TEST_TABLE_NAME, QueryUtil.getExplainPlan(rs));
-
-        ConnectionQueryServices services = conn.unwrap(PhoenixConnection.class).getQueryServices();
-        List<HRegionLocation> regions = services.getAllTableRegions(STATS_TEST_TABLE_BYTES);
-        assertEquals(1, regions.size());
 
         rs = conn.createStatement().executeQuery(
-                "SELECT GUIDE_POSTS_COUNT, REGION_NAME, GUIDE_POSTS_ROW_COUNT, MIN_KEY " +
-                " FROM SYSTEM.STATS WHERE PHYSICAL_NAME='"
-                        + STATS_TEST_TABLE_NAME + "' AND REGION_NAME IS NOT NULL");
-        assertTrue(rs.next());
-        assertEquals(nRows / 2, (rs.getLong(1)));
-        assertEquals(regions.get(0).getRegionInfo().getRegionNameAsString(), rs.getString(2));
-        //PhoenixArray arr = (PhoenixArray)rs.getArray(3);
-        assertEquals(20, rs.getLong(3));
-        assertTrue(Bytes.toString(rs.getBytes(4)).startsWith("a"));
-        assertFalse(rs.next());
+                "SELECT COLUMN_FAMILY,SUM(GUIDE_POSTS_ROW_COUNT),SUM(GUIDE_POSTS_WIDTH),COUNT(*) from SYSTEM.STATS where PHYSICAL_NAME = '"
+                        + STATS_TEST_TABLE_NAME_NEW + "' GROUP BY COLUMN_FAMILY");
 
-        byte[] midPoint = Bytes.toBytes(Character.toString((char)('a' + (5))));
-        splitTable(conn, midPoint, STATS_TEST_TABLE_BYTES);
-
-        keyRanges = getAllSplits(conn, STATS_TEST_TABLE_NAME);
-        assertEquals(12, keyRanges.size()); // Same number as before because split was at guidepost
-
-        regions = services.getAllTableRegions(STATS_TEST_TABLE_BYTES);
-        assertEquals(2, regions.size());
-        rs =
-                conn.createStatement()
-                        .executeQuery(
-                            "SELECT GUIDE_POSTS_COUNT, REGION_NAME, "
-                                    + "GUIDE_POSTS_ROW_COUNT, MIN_KEY " +
-                                    " FROM SYSTEM.STATS WHERE PHYSICAL_NAME='"
-                                    + STATS_TEST_TABLE_NAME + "' AND REGION_NAME IS NOT NULL");
         assertTrue(rs.next());
-        assertEquals(2, rs.getLong(1));
-        assertEquals(regions.get(0).getRegionInfo().getRegionNameAsString(), rs.getString(2));
-        //assertEquals(5, rs.getLong(3));
-        assertTrue(Bytes.toString(rs.getBytes(4)).startsWith("a"));
         assertTrue(rs.next());
-        assertEquals(8, rs.getLong(1));
-        assertEquals(regions.get(1).getRegionInfo().getRegionNameAsString(), rs.getString(2));
-        // This could even be 15 if the compaction thread completes after the update from split
-        //assertEquals(16, rs.getLong(3));
-        assertTrue(Bytes.toString(rs.getBytes(4)).startsWith("f"));
-        assertFalse(rs.next());
-
-        byte[] midPoint2 = Bytes.toBytes("cj");
-        splitTable(conn, midPoint2, STATS_TEST_TABLE_BYTES);
+        assertEquals("A", rs.getString(1));
+        assertEquals(25, rs.getInt(2));
+        assertEquals(11040, rs.getInt(3));
+        assertEquals(5, rs.getInt(4));
 
-        keyRanges = getAllSplits(conn, STATS_TEST_TABLE_NAME);
-        assertEquals((nRows / 2) + 3, keyRanges.size()); // One extra due to split between guideposts
-
-        regions = services.getAllTableRegions(STATS_TEST_TABLE_BYTES);
-        assertEquals(3, regions.size());
-        rs = conn.createStatement().executeQuery(
-                "SELECT GUIDE_POSTS_COUNT, REGION_NAME, GUIDE_POSTS_ROW_COUNT, MIN_KEY " +
-                "FROM SYSTEM.STATS WHERE PHYSICAL_NAME='"
-                        + STATS_TEST_TABLE_NAME + "' AND REGION_NAME IS NOT NULL");
         assertTrue(rs.next());
-        assertEquals(1, rs.getLong(1));
-        assertEquals(regions.get(0).getRegionInfo().getRegionNameAsString(), rs.getString(2));
-        // This value varies based on whether compaction updates or split updates the GPs
-        //assertEquals(3, rs.getLong(3));
-        assertTrue(Bytes.toString(rs.getBytes(4)).startsWith("a"));
+        assertEquals("B", rs.getString(1));
+        assertEquals(20, rs.getInt(2));
+        assertEquals(4432, rs.getInt(3));
+        assertEquals(2, rs.getInt(4));
+
         assertTrue(rs.next());
-        assertEquals(1, rs.getLong(1));
-        assertEquals(regions.get(1).getRegionInfo().getRegionNameAsString(), rs.getString(2));
-        assertTrue(Bytes.toString(rs.getBytes(4)).startsWith("d"));
-        //assertEquals(2, rs.getLong(3));
+        assertEquals("C", rs.getString(1));
+        assertEquals(25, rs.getInt(2));
+        assertEquals(6652, rs.getInt(3));
+        assertEquals(3, rs.getInt(4));
+
         assertTrue(rs.next());
-        assertEquals(8, rs.getLong(1));
-        assertEquals(regions.get(2).getRegionInfo().getRegionNameAsString(), rs.getString(2));
-        assertTrue(Bytes.toString(rs.getBytes(4)).startsWith("f"));
-        //assertEquals(16, rs.getLong(3));
-        assertFalse(rs.next());
-        rs = conn.createStatement().executeQuery("EXPLAIN SELECT * FROM " + STATS_TEST_TABLE_NAME);
-        assertEquals("CLIENT " + ((nRows / 2) + 3) + "-CHUNK " + "PARALLEL 1-WAY FULL SCAN OVER "
-                + STATS_TEST_TABLE_NAME, QueryUtil.getExplainPlan(rs));
+        assertEquals("D", rs.getString(1));
+        assertEquals(25, rs.getInt(2));
+        assertEquals(6652, rs.getInt(3));
+        assertEquals(3, rs.getInt(4));
 
-        TestUtil.analyzeTable(conn, STATS_TEST_TABLE_NAME);
-        rs = conn.createStatement().executeQuery("EXPLAIN SELECT * FROM " + STATS_TEST_TABLE_NAME);
-        assertEquals("CLIENT " + ((nRows / 2) + 2) + "-CHUNK " + "PARALLEL 1-WAY FULL SCAN OVER "
-                + STATS_TEST_TABLE_NAME, QueryUtil.getExplainPlan(rs));
-        infos = TestUtil.getGuidePostsList(conn, STATS_TEST_TABLE_NAME);
-        for (GuidePostsInfo info : infos) {
-            assertEquals(20, info.getRowCount());
-            assertEquals(9936, info.getByteCount());
-            break;
-        }
-        conn.close();
     }
+
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/3e740cbc/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java
index bf4a192..b7b936e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataProtocol.java
@@ -73,7 +73,7 @@ public abstract class MetaDataProtocol extends MetaDataService {
     public static final long MIN_SYSTEM_TABLE_TIMESTAMP_4_3_0 = MIN_TABLE_TIMESTAMP + 7;
     public static final long MIN_SYSTEM_TABLE_TIMESTAMP_4_5_0 = MIN_TABLE_TIMESTAMP + 8;
     public static final long MIN_SYSTEM_TABLE_TIMESTAMP_4_6_0 = MIN_TABLE_TIMESTAMP + 9;
-    public static final long MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0 = MIN_TABLE_TIMESTAMP + 10;
+    public static final long MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0 = MIN_TABLE_TIMESTAMP + 11;
     // MIN_SYSTEM_TABLE_TIMESTAMP needs to be set to the max of all the MIN_SYSTEM_TABLE_TIMESTAMP_* constants
     public static final long MIN_SYSTEM_TABLE_TIMESTAMP = MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0;
     // TODO: pare this down to minimum, as we don't need duplicates for both table and column errors, nor should we need

http://git-wip-us.apache.org/repos/asf/phoenix/blob/3e740cbc/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
index 4602628..ddb833c 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/UngroupedAggregateRegionObserver.java
@@ -21,9 +21,7 @@ import static org.apache.phoenix.query.QueryConstants.AGG_TIMESTAMP;
 import static org.apache.phoenix.query.QueryConstants.SINGLE_COLUMN;
 import static org.apache.phoenix.query.QueryConstants.SINGLE_COLUMN_FAMILY;
 import static org.apache.phoenix.query.QueryConstants.UNGROUPED_AGG_ROW_KEY;
-import static org.apache.phoenix.query.QueryServices.COMMIT_STATS_ASYNC;
 import static org.apache.phoenix.query.QueryServices.MUTATE_BATCH_SIZE_ATTRIB;
-import static org.apache.phoenix.query.QueryServicesOptions.DEFAULT_COMMIT_STATS_ASYNC;
 import static org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker.COMPACTION_UPDATE_STATS_ROW_COUNT;
 import static org.apache.phoenix.schema.stats.StatisticsCollectionRunTracker.CONCURRENT_UPDATE_STATS_ROW_COUNT;
 
@@ -32,7 +30,6 @@ import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
-import java.security.PrivilegedExceptionAction;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -41,8 +38,6 @@ import java.util.List;
 import java.util.Set;
 import java.util.concurrent.Callable;
 
-import co.cask.tephra.TxConstants;
-
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.Cell;
 import org.apache.hadoop.hbase.CoprocessorEnvironment;
@@ -65,7 +60,6 @@ import org.apache.hadoop.hbase.regionserver.InternalScanner;
 import org.apache.hadoop.hbase.regionserver.RegionScanner;
 import org.apache.hadoop.hbase.regionserver.ScanType;
 import org.apache.hadoop.hbase.regionserver.Store;
-import org.apache.hadoop.hbase.security.User;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.hadoop.hbase.util.Pair;
 import org.apache.hadoop.io.WritableUtils;
@@ -122,6 +116,8 @@ import com.google.common.base.Throwables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 
+import co.cask.tephra.TxConstants;
+
 
 /**
  * Region observer that aggregates ungrouped rows(i.e. SQL query with aggregation function and no GROUP BY).
@@ -654,59 +650,6 @@ public class UngroupedAggregateRegionObserver extends BaseScannerRegionObserver
     }
 
 
-    @Override
-    public void postSplit(final ObserverContext<RegionCoprocessorEnvironment> e, final HRegion l,
-            final HRegion r) throws IOException {
-        final Configuration config = e.getEnvironment().getConfiguration();
-        boolean async = config.getBoolean(COMMIT_STATS_ASYNC, DEFAULT_COMMIT_STATS_ASYNC);
-        if (!async) {
-            splitStatsInternal(e, l, r);
-        } else {
-            StatisticsCollectionRunTracker.getInstance(config).runTask(new Callable<Void>() {
-                @Override
-                public Void call() throws Exception {
-                    splitStatsInternal(e, l, r);
-                    return null;
-                }
-            });
-        }
-    }
-
-    private void splitStatsInternal(final ObserverContext<RegionCoprocessorEnvironment> e,
-            final HRegion l, final HRegion r) {
-        final RegionCoprocessorEnvironment env = e.getEnvironment();
-        final HRegion region = env.getRegion();
-        final TableName table = region.getRegionInfo().getTable();
-        try {
-            boolean useCurrentTime =
-                    env.getConfiguration().getBoolean(QueryServices.STATS_USE_CURRENT_TIME_ATTRIB,
-                            QueryServicesOptions.DEFAULT_STATS_USE_CURRENT_TIME);
-            // Provides a means of clients controlling their timestamps to not use current time
-            // when background tasks are updating stats. Instead we track the max timestamp of
-            // the cells and use that.
-            final long clientTimeStamp = useCurrentTime ? TimeKeeper.SYSTEM.getCurrentTime() :
-              StatisticsCollector.NO_TIMESTAMP;
-            User.runAsLoginUser(new PrivilegedExceptionAction<Void>() {
-              @Override
-              public Void run() throws Exception {
-                StatisticsCollector stats = new StatisticsCollector(env,
-                  table.getNameAsString(), clientTimeStamp);
-                try {
-                  stats.splitStats(region, l, r);
-                  return null;
-                } finally {
-                  if (stats != null) stats.close();
-                }
-              }
-            });
-        } catch (IOException ioe) {
-            if(logger.isWarnEnabled()) {
-                logger.warn("Error while collecting stats during split for " + table,ioe);
-            }
-        }
-    }
-
-
     private static PTable deserializeTable(byte[] b) {
         try {
             PTableProtos.PTable ptableProto = PTableProtos.PTable.parseFrom(b);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/3e740cbc/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
index 21bd591..246c9e2 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
@@ -84,22 +84,24 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData {
     public static final int SCHEMA_NAME_INDEX = 1;
     public static final int TENANT_ID_INDEX = 0;
 
-
     public static final int TYPE_INDEX = 2;
     public static final int FUNTION_NAME_INDEX = 1;
-    
 
     public static final String SYSTEM_CATALOG_SCHEMA = QueryConstants.SYSTEM_SCHEMA_NAME;
     public static final byte[] SYSTEM_CATALOG_SCHEMA_BYTES = QueryConstants.SYSTEM_SCHEMA_NAME_BYTES;
+    public static final String SYSTEM_SCHEMA_NAME = QueryConstants.SYSTEM_SCHEMA_NAME;
+    public static final byte[] SYSTEM_SCHEMA_NAME_BYTES = QueryConstants.SYSTEM_SCHEMA_NAME_BYTES;
+
     public static final String SYSTEM_CATALOG_TABLE = "CATALOG";
     public static final byte[] SYSTEM_CATALOG_TABLE_BYTES = Bytes.toBytes(SYSTEM_CATALOG_TABLE);
     public static final String SYSTEM_CATALOG = SYSTEM_CATALOG_SCHEMA + ".\"" + SYSTEM_CATALOG_TABLE + "\"";
-    public static final String SYSTEM_CATALOG_NAME = SchemaUtil.getTableName(SYSTEM_CATALOG_SCHEMA, SYSTEM_CATALOG_TABLE);
+    public static final String SYSTEM_CATALOG_NAME = SchemaUtil.getTableName(SYSTEM_CATALOG_SCHEMA,
+            SYSTEM_CATALOG_TABLE);
     public static final byte[] SYSTEM_CATALOG_NAME_BYTES = Bytes.toBytes(SYSTEM_CATALOG_NAME);
     public static final String SYSTEM_STATS_TABLE = "STATS";
     public static final String SYSTEM_STATS_NAME = SchemaUtil.getTableName(SYSTEM_CATALOG_SCHEMA, SYSTEM_STATS_TABLE);
     public static final byte[] SYSTEM_STATS_NAME_BYTES = Bytes.toBytes(SYSTEM_STATS_NAME);
-
+    public static final byte[] SYSTEM_STATS_TABLE_BYTES = Bytes.toBytes(SYSTEM_STATS_TABLE);
     public static final String SYSTEM_CATALOG_ALIAS = "\"SYSTEM.TABLE\"";
 
     public static final String TABLE_NAME = "TABLE_NAME";
@@ -272,6 +274,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData {
     public static final byte[] MAX_KEY_BYTES = Bytes.toBytes(MAX_KEY);
     public static final String LAST_STATS_UPDATE_TIME = "LAST_STATS_UPDATE_TIME";
     public static final byte[] LAST_STATS_UPDATE_TIME_BYTES = Bytes.toBytes(LAST_STATS_UPDATE_TIME);
+    public static final String GUIDE_POST_KEY = "GUIDE_POST_KEY";
 
     public static final String PARENT_TENANT_ID = "PARENT_TENANT_ID";
     public static final byte[] PARENT_TENANT_ID_BYTES = Bytes.toBytes(PARENT_TENANT_ID);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/3e740cbc/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
index f0ab327..6ad3e0c 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
@@ -2417,6 +2417,10 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
                                     columnsToAdd = PhoenixDatabaseMetaData.TRANSACTIONAL + " " + PBoolean.INSTANCE.getSqlTypeName();
                                     metaConnection = addColumn(metaConnection, PhoenixDatabaseMetaData.SYSTEM_CATALOG,
                                             MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0, columnsToAdd, false);
+									// Drop old stats table so that new stats
+									// table
+									metaConnection = dropStatsTable(metaConnection,
+											MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0 - 1);
                                 }
                                 
                             }
@@ -2532,6 +2536,80 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
         }
     }
     
+	private PhoenixConnection dropStatsTable(PhoenixConnection oldMetaConnection, long timestamp)
+			throws SQLException, IOException {
+		Properties props = PropertiesUtil.deepCopy(oldMetaConnection.getClientInfo());
+		props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(timestamp));
+		PhoenixConnection metaConnection = new PhoenixConnection(oldMetaConnection, this, props);
+		SQLException sqlE = null;
+		boolean wasCommit = metaConnection.getAutoCommit();
+		try {
+			metaConnection.setAutoCommit(true);
+			metaConnection.createStatement()
+					.executeUpdate("DELETE FROM " + PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME + " WHERE "
+							+ PhoenixDatabaseMetaData.TABLE_NAME + "='" + PhoenixDatabaseMetaData.SYSTEM_STATS_TABLE
+							+ "' AND " + PhoenixDatabaseMetaData.TABLE_SCHEM + "='"
+							+ PhoenixDatabaseMetaData.SYSTEM_SCHEMA_NAME + "'");
+		} catch (SQLException e) {
+			logger.warn("exception during upgrading stats table:" + e);
+			sqlE = e;
+		} finally {
+			try {
+				metaConnection.setAutoCommit(wasCommit);
+				oldMetaConnection.close();
+			} catch (SQLException e) {
+				if (sqlE != null) {
+					sqlE.setNextException(e);
+				} else {
+					sqlE = e;
+				}
+			}
+			if (sqlE != null) {
+				throw sqlE;
+			}
+		}
+
+		HBaseAdmin admin = null;
+		try {
+			admin = getAdmin();
+			admin.disableTable(PhoenixDatabaseMetaData.SYSTEM_STATS_NAME_BYTES);
+			try {
+				admin.deleteTable(PhoenixDatabaseMetaData.SYSTEM_STATS_NAME_BYTES);
+			} catch (org.apache.hadoop.hbase.TableNotFoundException e) {
+				logger.debug("Stats table was not found during upgrade!!");
+			}
+		} finally {
+			if (admin != null)
+				admin.close();
+		}
+		oldMetaConnection = metaConnection;
+		props = PropertiesUtil.deepCopy(oldMetaConnection.getClientInfo());
+		props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB,
+				Long.toString(MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP_4_7_0));
+		try {
+			metaConnection = new PhoenixConnection(oldMetaConnection, ConnectionQueryServicesImpl.this, props);
+		} finally {
+			try {
+				oldMetaConnection.close();
+			} catch (SQLException e) {
+				if (sqlE != null) {
+					sqlE.setNextException(e);
+				} else {
+					sqlE = e;
+				}
+			}
+			if (sqlE != null) {
+				throw sqlE;
+			}
+		}
+		metaConnection.removeTable(null, PhoenixDatabaseMetaData.SYSTEM_SCHEMA_NAME,
+				PhoenixDatabaseMetaData.SYSTEM_STATS_TABLE, MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP);
+		clearTableFromCache(ByteUtil.EMPTY_BYTE_ARRAY, PhoenixDatabaseMetaData.SYSTEM_SCHEMA_NAME_BYTES,
+				PhoenixDatabaseMetaData.SYSTEM_STATS_TABLE_BYTES, MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP);
+		clearTableRegionCache(PhoenixDatabaseMetaData.SYSTEM_STATS_NAME_BYTES);
+		return metaConnection;
+	}
+    
     private static int getSaltBuckets(TableAlreadyExistsException e) {
         PTable table = e.getTable();
         Integer sequenceSaltBuckets = table == null ? null : table.getBucketNum();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/3e740cbc/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
index 1cac37f..c1cb0c0 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/QueryConstants.java
@@ -39,10 +39,9 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.DEFAULT_COLUMN_FAM
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.DEFAULT_VALUE;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.DISABLE_WAL;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.FUNCTION_NAME;
-import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.GUIDE_POSTS;
-import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.GUIDE_POSTS_COUNT;
-import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.GUIDE_POSTS_ROW_COUNT;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.GUIDE_POSTS_WIDTH;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.GUIDE_POST_KEY;
+import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.GUIDE_POSTS_ROW_COUNT;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.IMMUTABLE_ROWS;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.INCREMENT_BY;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.INDEX_DISABLE_TIMESTAMP;
@@ -59,9 +58,7 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.KEY_SEQ;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.LAST_STATS_UPDATE_TIME;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.LIMIT_REACHED_FLAG;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.LINK_TYPE;
-import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.MAX_KEY;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.MAX_VALUE;
-import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.MIN_KEY;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.MIN_VALUE;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.MULTI_TENANT;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.NULLABLE;
@@ -71,7 +68,6 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.ORDINAL_POSITION;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.PHYSICAL_NAME;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.PK_NAME;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.REF_GENERATION;
-import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.REGION_NAME;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.REMARKS;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.RETURN_TYPE;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SALT_BUCKETS;
@@ -274,17 +270,13 @@ public interface QueryConstants {
             // PK columns
             PHYSICAL_NAME  + " VARCHAR NOT NULL," +
             COLUMN_FAMILY + " VARCHAR," +
-            REGION_NAME + " VARCHAR," +
-            GUIDE_POSTS_COUNT + " BIGINT," +
-            GUIDE_POSTS  + " VARBINARY," +
+            GUIDE_POST_KEY  + " VARBINARY," +
             GUIDE_POSTS_WIDTH + " BIGINT," +
-            MIN_KEY + " VARBINARY," +
-            MAX_KEY + " VARBINARY," +
             LAST_STATS_UPDATE_TIME+ " DATE, "+
             GUIDE_POSTS_ROW_COUNT+ " BIGINT, "+
             "CONSTRAINT " + SYSTEM_TABLE_PK_NAME + " PRIMARY KEY ("
             + PHYSICAL_NAME + ","
-            + COLUMN_FAMILY + ","+ REGION_NAME+"))\n" +
+            + COLUMN_FAMILY + ","+ GUIDE_POST_KEY+"))\n" +
             HConstants.VERSIONS + "=" + MetaDataProtocol.DEFAULT_MAX_STAT_DATA_VERSIONS + ",\n" +
             HColumnDescriptor.KEEP_DELETED_CELLS + "="  + MetaDataProtocol.DEFAULT_META_DATA_KEEP_DELETED_CELLS + ",\n" +
             // Install split policy to prevent a physical table's stats from being split across regions.

http://git-wip-us.apache.org/repos/asf/phoenix/blob/3e740cbc/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
index 7ee30fb..decc944 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
@@ -60,7 +60,6 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.ORDINAL_POSITION;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.PARENT_TENANT_ID;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.PHYSICAL_NAME;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.PK_NAME;
-import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.REGION_NAME;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.RETURN_TYPE;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SALT_BUCKETS;
 import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SORT_ORDER;
@@ -925,7 +924,7 @@ public class MetaDataClient {
         long clientTimeStamp = connection.getSCN() == null ? HConstants.LATEST_TIMESTAMP : scn;
         String query = "SELECT CURRENT_DATE()," + LAST_STATS_UPDATE_TIME + " FROM " + PhoenixDatabaseMetaData.SYSTEM_STATS_NAME
                 + " WHERE " + PHYSICAL_NAME + "='" + physicalName.getString() + "' AND " + COLUMN_FAMILY
-                + " IS NULL AND " + REGION_NAME + " IS NULL AND " + LAST_STATS_UPDATE_TIME + " IS NOT NULL";
+                + " IS NULL AND " + LAST_STATS_UPDATE_TIME + " IS NOT NULL";
         ResultSet rs = connection.createStatement().executeQuery(query);
         long msSinceLastUpdate = Long.MAX_VALUE;
         if (rs.next()) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/3e740cbc/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/GuidePostsInfo.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/GuidePostsInfo.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/GuidePostsInfo.java
index b8b64ae..0f1dbeb 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/GuidePostsInfo.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/GuidePostsInfo.java
@@ -17,17 +17,11 @@
  */
 package org.apache.phoenix.schema.stats;
 
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.hadoop.io.WritableUtils;
-import org.apache.phoenix.util.TrustedByteArrayOutputStream;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
@@ -126,7 +120,7 @@ public class GuidePostsInfo {
      * @param byteCount
      * @return
      */
-    public boolean addGuidePost(byte[] row, long byteCount) {
+    public boolean addGuidePost(byte[] row, long byteCount, long rowCount) {
         if (guidePosts.isEmpty() || Bytes.compareTo(row, guidePosts.get(guidePosts.size() - 1)) > 0) {
             List<byte[]> newGuidePosts = Lists.newArrayListWithExpectedSize(this.getGuidePosts().size() + 1);
             newGuidePosts.addAll(guidePosts);
@@ -134,93 +128,18 @@ public class GuidePostsInfo {
             this.guidePosts = ImmutableList.copyOf(newGuidePosts);
             this.byteCount += byteCount;
             this.keyByteSize += row.length;
+            this.rowCount+=rowCount;
             return true;
         }
         return false;
     }
     
-    /**
-     * Deserializes the per row guidePosts info from the value part of each cell in the SYSTEM.STATS table
-     * @param buf
-     * @param offset
-     * @param l
-     * @param rowCount
-     * @return the GuidePostsInfo instance formed by deserializing the byte[]
-     */
-    public static GuidePostsInfo deserializeGuidePostsInfo(byte[] buf, int offset, int l,
-            long rowCount) {
-        try {
-            ByteArrayInputStream bytesIn = new ByteArrayInputStream(buf, offset, l);
-            try {
-                DataInputStream in = new DataInputStream(bytesIn);
-                try {
-                    long byteCount = in.readLong();
-                    int guidepostsCount = in.readInt();
-                    List<byte[]> guidePosts = Lists.newArrayListWithExpectedSize(guidepostsCount);
-                    if (guidepostsCount > 0) {
-                        for (int i = 0; i < guidepostsCount; i++) {
-                            int length = WritableUtils.readVInt(in);
-                            byte[] gp = new byte[length];
-                            in.read(gp);
-                            if (gp.length != 0) {
-                                guidePosts.add(gp);
-                            }
-                        }
-                    }
-                    return new GuidePostsInfo(byteCount, guidePosts, rowCount);
-                } catch (IOException e) {
-                    throw new RuntimeException(e); // not possible
-                } finally {
-                    try {
-                        in.close();
-                    } catch (IOException e) {
-                        throw new RuntimeException(e); // not possible
-                    }
-                }
-            } finally {
-                bytesIn.close();
-            }
-        } catch (IOException e) {
-            throw new RuntimeException(e); // not possible
-        }
+    public boolean addGuidePost(byte[] row) {
+        return addGuidePost(row, 0, 0);
     }
 
-    /**
-     * Serailizes the guidePosts info as value in the SYSTEM.STATS table.
-     * <br>
-     * The format is,
-     * <br>
-     *  - number of bytes traversed
-     * <br>
-     *  - number of key bytes in the region
-     * <br>
-     *  - number of guideposts for that family
-     * <br> u
-     *  - [guidepostSize][guidePostsArray],[guidePostsSize][guidePostArray]
-     * @return the byte[] to be serialized in the cell
-     */
-    public byte[] serializeGuidePostsInfo() {
-        int size = guidePosts.size();
-        // We will lose precision here?
-        TrustedByteArrayOutputStream bs = new TrustedByteArrayOutputStream((int)(Bytes.SIZEOF_LONG + Bytes.SIZEOF_LONG
-                + Bytes.SIZEOF_INT + this.keyByteSize + (WritableUtils.getVIntSize(size) * size)));
-        DataOutputStream os = new DataOutputStream(bs);
-        try {
-            os.writeLong(byteCount);
-            os.writeInt(size);
-            for (byte[] element : guidePosts) {
-                WritableUtils.writeVInt(os, element.length);
-                os.write(element);
-            }
-            return bs.toByteArray();
-        } catch (IOException ioe) {
-            throw new RuntimeException(ioe); // not possible
-        } finally {
-            try {
-                os.close();
-            } catch (IOException ioe) {
-                throw new RuntimeException(ioe); // not possible
-            }
-        }
+    public boolean addGuidePost(byte[] row, long byteCount) {
+        return addGuidePost(row, byteCount, 0);
     }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/3e740cbc/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsCollector.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsCollector.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsCollector.java
index 07fef1c..76eef58 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsCollector.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsCollector.java
@@ -25,7 +25,6 @@ import java.util.Map;
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.Cell;
-import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.KeyValue;
 import org.apache.hadoop.hbase.KeyValueUtil;
@@ -48,16 +47,13 @@ import org.apache.phoenix.util.TimeKeeper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
 /**
- * A default implementation of the Statistics tracker that helps to collect stats like min key, max key and
- * guideposts.
- * TODO: review timestamps used for stats. We support the user controlling the timestamps, so we should
- * honor that with timestamps for stats as well. The issue is for compaction, though. I don't know of
- * a way for the user to specify any timestamp for that. Perhaps best to use current time across the
- * board for now.
+ * A default implementation of the Statistics tracker that helps to collect stats like min key, max key and guideposts.
+ * TODO: review timestamps used for stats. We support the user controlling the timestamps, so we should honor that with
+ * timestamps for stats as well. The issue is for compaction, though. I don't know of a way for the user to specify any
+ * timestamp for that. Perhaps best to use current time across the board for now.
  */
 public class StatisticsCollector {
     private static final Logger logger = LoggerFactory.getLogger(StatisticsCollector.class);
@@ -65,49 +61,53 @@ public class StatisticsCollector {
 
     private long guidepostDepth;
     private long maxTimeStamp = MetaDataProtocol.MIN_TABLE_TIMESTAMP;
-    private Map<ImmutableBytesPtr, Pair<Long,GuidePostsInfo>> guidePostsMap = Maps.newHashMap();
+    private Map<ImmutableBytesPtr, Pair<Long, GuidePostsInfo>> guidePostsMap = Maps.newHashMap();
     protected StatisticsWriter statsTable;
-    private Pair<Long,GuidePostsInfo> cachedGps = null;
-    // Store minKey and maxKey at the tracker level itself so that we don't need to do 
-    // any comparison for the min/max values for every next() call
-    private byte[] minKey;
-    private int minKeyOffset, minKeyLength;
+    private Pair<Long, GuidePostsInfo> cachedGps = null;
 
-    public StatisticsCollector(RegionCoprocessorEnvironment env, String tableName, long clientTimeStamp) throws IOException {
+    public StatisticsCollector(RegionCoprocessorEnvironment env, String tableName, long clientTimeStamp)
+            throws IOException {
         this(env, tableName, clientTimeStamp, null, null, null);
     }
 
-    public StatisticsCollector(RegionCoprocessorEnvironment env, String tableName, long clientTimeStamp, byte[] gp_width_bytes, byte[] gp_per_region_bytes) throws IOException {
+    public StatisticsCollector(RegionCoprocessorEnvironment env, String tableName, long clientTimeStamp,
+            byte[] gp_width_bytes, byte[] gp_per_region_bytes) throws IOException {
         this(env, tableName, clientTimeStamp, null, gp_width_bytes, gp_per_region_bytes);
     }
 
-    public StatisticsCollector(RegionCoprocessorEnvironment env, String tableName, long clientTimeStamp, byte[] family) throws IOException {
+    public StatisticsCollector(RegionCoprocessorEnvironment env, String tableName, long clientTimeStamp, byte[] family)
+            throws IOException {
         this(env, tableName, clientTimeStamp, family, null, null);
     }
 
-    public StatisticsCollector(RegionCoprocessorEnvironment env, String tableName, long clientTimeStamp, byte[] family, byte[] gp_width_bytes, byte[] gp_per_region_bytes) throws IOException {
+    public StatisticsCollector(RegionCoprocessorEnvironment env, String tableName, long clientTimeStamp, byte[] family,
+            byte[] gp_width_bytes, byte[] gp_per_region_bytes) throws IOException {
         Configuration config = env.getConfiguration();
-        int guidepostPerRegion = gp_per_region_bytes == null ? config.getInt(QueryServices.STATS_GUIDEPOST_PER_REGION_ATTRIB, 
-                QueryServicesOptions.DEFAULT_STATS_GUIDEPOST_PER_REGION) : PInteger.INSTANCE.getCodec().decodeInt(gp_per_region_bytes, 0, SortOrder.getDefault());
-        long guidepostWidth = gp_width_bytes == null ? config.getLong(QueryServices.STATS_GUIDEPOST_WIDTH_BYTES_ATTRIB,
-                QueryServicesOptions.DEFAULT_STATS_GUIDEPOST_WIDTH_BYTES) : PLong.INSTANCE.getCodec().decodeInt(gp_width_bytes, 0, SortOrder.getDefault());
-        this.guidepostDepth = StatisticsUtil.getGuidePostDepth(guidepostPerRegion, guidepostWidth, env.getRegion().getTableDesc());
+        int guidepostPerRegion = gp_per_region_bytes == null
+                ? config.getInt(QueryServices.STATS_GUIDEPOST_PER_REGION_ATTRIB,
+                        QueryServicesOptions.DEFAULT_STATS_GUIDEPOST_PER_REGION)
+                : PInteger.INSTANCE.getCodec().decodeInt(gp_per_region_bytes, 0, SortOrder.getDefault());
+        long guidepostWidth = gp_width_bytes == null
+                ? config.getLong(QueryServices.STATS_GUIDEPOST_WIDTH_BYTES_ATTRIB,
+                        QueryServicesOptions.DEFAULT_STATS_GUIDEPOST_WIDTH_BYTES)
+                : PLong.INSTANCE.getCodec().decodeInt(gp_width_bytes, 0, SortOrder.getDefault());
+        this.guidepostDepth = StatisticsUtil.getGuidePostDepth(guidepostPerRegion, guidepostWidth,
+                env.getRegion().getTableDesc());
         // Get the stats table associated with the current table on which the CP is
         // triggered
         this.statsTable = StatisticsWriter.newWriter(env, tableName, clientTimeStamp);
         // in a compaction we know the one family ahead of time
         if (family != null) {
             ImmutableBytesPtr cfKey = new ImmutableBytesPtr(family);
-            cachedGps = new Pair<Long, GuidePostsInfo>(0l, new GuidePostsInfo(0,
-                    Collections.<byte[]> emptyList(), 0l));
+            cachedGps = new Pair<Long, GuidePostsInfo>(0l, new GuidePostsInfo(0, Collections.<byte[]> emptyList(), 0l));
             guidePostsMap.put(cfKey, cachedGps);
         }
     }
-    
+
     public long getMaxTimeStamp() {
         return maxTimeStamp;
     }
-    
+
     public void close() throws IOException {
         this.statsTable.close();
     }
@@ -127,31 +127,27 @@ public class StatisticsCollector {
         }
     }
     
-    private void writeStatsToStatsTable(final HRegion region,
-            boolean delete, List<Mutation> mutations, long currentTime) throws IOException {
-        try {
-            // update the statistics table
-            for (ImmutableBytesPtr fam : guidePostsMap.keySet()) {
-                if (delete) {
-                    if(logger.isDebugEnabled()) {
-                        logger.debug("Deleting the stats for the region "+region.getRegionInfo());
-                    }
-                    statsTable.deleteStats(region.getRegionInfo().getRegionName(), this, fam,
-                            mutations);
-                }
-                if(logger.isDebugEnabled()) {
-                    logger.debug("Adding new stats for the region "+region.getRegionInfo());
-                }
-                statsTable.addStats((region.getRegionInfo().getRegionName()), this, fam,
-                        mutations);
-            }
-            // Clear minKey and maxKey
-            clearMinKeys();
-        } catch (IOException e) {
-            logger.error("Failed to update statistics table!", e);
-            throw e;
-        }
-    }
+	private void writeStatsToStatsTable(final HRegion region, boolean delete, List<Mutation> mutations, long currentTime)
+			throws IOException {
+		try {
+			// update the statistics table
+			for (ImmutableBytesPtr fam : guidePostsMap.keySet()) {
+				if (delete) {
+					if (logger.isDebugEnabled()) {
+						logger.debug("Deleting the stats for the region " + region.getRegionInfo());
+					}
+					statsTable.deleteStats(region, this, fam, mutations);
+				}
+				if (logger.isDebugEnabled()) {
+					logger.debug("Adding new stats for the region " + region.getRegionInfo());
+				}
+				statsTable.addStats(this, fam, mutations);
+			}
+		} catch (IOException e) {
+			logger.error("Failed to update statistics table!", e);
+			throw e;
+		}
+	}
 
     private void commitStats(List<Mutation> mutations) throws IOException {
         statsTable.commitStats(mutations);
@@ -166,15 +162,8 @@ public class StatisticsCollector {
     public void collectStatistics(final List<Cell> results) {
         Map<ImmutableBytesPtr, Boolean> famMap = Maps.newHashMap();
         List<GuidePostsInfo> rowTracker = null;
-        if(cachedGps == null) {
-            rowTracker = 
-                    new ArrayList<GuidePostsInfo>();
-        }
-        if (minKey == null && !results.isEmpty()) {
-            Cell minCell = results.get(0);
-            minKey = minCell.getRowArray();
-            minKeyOffset =  minCell.getRowOffset();
-            minKeyLength = minCell.getRowLength();
+        if (cachedGps == null) {
+            rowTracker = new ArrayList<GuidePostsInfo>();
         }
         for (Cell cell : results) {
             KeyValue kv = KeyValueUtil.ensureKeyValue(cell);
@@ -185,8 +174,8 @@ public class StatisticsCollector {
                         kv.getFamilyLength());
                 gps = guidePostsMap.get(cfKey);
                 if (gps == null) {
-                    gps = new Pair<Long, GuidePostsInfo>(0l, new GuidePostsInfo(0,
-                            Collections.<byte[]> emptyList(), 0l));
+                    gps = new Pair<Long, GuidePostsInfo>(0l,
+                            new GuidePostsInfo(0, Collections.<byte[]> emptyList(), 0l));
                     guidePostsMap.put(cfKey, gps);
                 }
                 if (famMap.get(cfKey) == null) {
@@ -200,14 +189,14 @@ public class StatisticsCollector {
             long byteCount = gps.getFirst() + kvLength;
             gps.setFirst(byteCount);
             if (byteCount >= guidepostDepth) {
-                byte[] row = ByteUtil.copyKeyBytesIfNecessary(new ImmutableBytesWritable(kv.getRowArray(), kv
-                        .getRowOffset(), kv.getRowLength()));
+                byte[] row = ByteUtil.copyKeyBytesIfNecessary(
+                        new ImmutableBytesWritable(kv.getRowArray(), kv.getRowOffset(), kv.getRowLength()));
                 if (gps.getSecond().addGuidePost(row, byteCount)) {
                     gps.setFirst(0l);
                 }
             }
         }
-        if(cachedGps == null) {
+        if (cachedGps == null) {
             for (GuidePostsInfo s : rowTracker) {
                 s.incrementRowCount();
             }
@@ -226,25 +215,6 @@ public class StatisticsCollector {
         return getInternalScanner(env, store, s, cfKey, mergeRegions);
     }
 
-    public void splitStats(HRegion parent, HRegion left, HRegion right) {
-        try {
-            if (logger.isDebugEnabled()) {
-                logger.debug("Collecting stats for split of " + parent.getRegionInfo() + " into " + left.getRegionInfo() + " and " + right.getRegionInfo());
-            }
-            List<Mutation> mutations = Lists.newArrayListWithExpectedSize(3);
-            for (byte[] fam : parent.getStores().keySet()) {
-            	statsTable.splitStats(parent, left, right, this, new ImmutableBytesPtr(fam), mutations);
-            }
-            if (logger.isDebugEnabled()) {
-                logger.debug("Committing stats for the daughter regions as part of split " + parent.getRegionInfo());
-            }
-            commitStats(mutations);
-        } catch (IOException e) {
-            logger.error("Error while capturing stats after split of region "
-                    + parent.getRegionInfo().getRegionNameAsString(), e);
-        }
-    }
-
     protected InternalScanner getInternalScanner(RegionCoprocessorEnvironment env, Store store, InternalScanner internalScan,
             ImmutableBytesPtr family, Pair<HRegionInfo, HRegionInfo> mergeRegions) {
         return new StatisticsScanner(this, statsTable, env, internalScan, family, mergeRegions);
@@ -253,12 +223,6 @@ public class StatisticsCollector {
     public void clear() {
         this.guidePostsMap.clear();
         maxTimeStamp = MetaDataProtocol.MIN_TABLE_TIMESTAMP;
-        clearMinKeys();
-    }
-
-    private void clearMinKeys() {
-        minKey = null;
-        minKeyOffset = minKeyLength = 0;
     }
 
     public void addGuidePost(ImmutableBytesPtr cfKey, GuidePostsInfo info, long byteSize,
@@ -270,24 +234,12 @@ public class StatisticsCollector {
             newInfo.setFirst(oldInfo.getFirst() + newInfo.getFirst());
         }
         maxTimeStamp = Math.max(maxTimeStamp, timestamp);
-        this.minKey = minKey;
-        this.minKeyOffset = 0;
-        this.minKeyLength = this.minKey.length;
     }
 
     public GuidePostsInfo getGuidePosts(ImmutableBytesPtr fam) {
-        Pair<Long,GuidePostsInfo> pair = guidePostsMap.get(fam);
-        if (pair != null) {
-            return pair.getSecond();
-        }
+        Pair<Long, GuidePostsInfo> pair = guidePostsMap.get(fam);
+        if (pair != null) { return pair.getSecond(); }
         return null;
     }
 
-    public void getMinKey(ImmutableBytesWritable ptr) {
-        if (minKey != null) {
-            ptr.set(minKey, minKeyOffset, minKeyLength);
-        } else {
-            ptr.set(HConstants.EMPTY_BYTE_ARRAY);
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/3e740cbc/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsScanner.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsScanner.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsScanner.java
index 550a772..9721a5e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsScanner.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsScanner.java
@@ -89,7 +89,7 @@ public class StatisticsScanner implements InternalScanner {
             tracker.collectStatistics(results);
         }
     }
-    
+
     private class StatisticsScannerCallable implements Callable<Void> {
         @Override
         public Void call() throws IOException {
@@ -100,32 +100,16 @@ public class StatisticsScanner implements InternalScanner {
                 // update the statistics table
                 // Just verify if this if fine
                 ArrayList<Mutation> mutations = new ArrayList<Mutation>();
-                if (mergeRegions != null) {
-                    if (mergeRegions.getFirst() != null) {
-                        if (LOG.isDebugEnabled()) {
-                            LOG.debug("Deleting stale stats for the region "
-                                    + mergeRegions.getFirst().getRegionNameAsString() + " as part of major compaction");
-                        }
-                        stats.deleteStats(mergeRegions.getFirst().getRegionName(), tracker, family, mutations);
-                    }
-                    if (mergeRegions.getSecond() != null) {
-                        if (LOG.isDebugEnabled()) {
-                            LOG.debug("Deleting stale stats for the region "
-                                    + mergeRegions.getSecond().getRegionNameAsString() + " as part of major compaction");
-                        }
-                        stats.deleteStats(mergeRegions.getSecond().getRegionName(), tracker, family, mutations);
-                    }
-                }
                 if (LOG.isDebugEnabled()) {
                     LOG.debug("Deleting the stats for the region " + region.getRegionNameAsString()
                         + " as part of major compaction");
                 }
-                stats.deleteStats(region.getRegionName(), tracker, family, mutations);
+                stats.deleteStats(region, tracker, family, mutations);
                 if (LOG.isDebugEnabled()) {
                     LOG.debug("Adding new stats for the region " + region.getRegionNameAsString()
                         + " as part of major compaction");
                 }
-                stats.addStats(region.getRegionName(), tracker, family, mutations);
+                stats.addStats(tracker, family, mutations);
                 if (LOG.isDebugEnabled()) {
                     LOG.debug("Committing new stats for the region " + region.getRegionNameAsString()
                         + " as part of major compaction");

http://git-wip-us.apache.org/repos/asf/phoenix/blob/3e740cbc/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java
index e692470..16f249c 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsUtil.java
@@ -19,7 +19,10 @@ package org.apache.phoenix.schema.stats;
 import static org.apache.phoenix.util.SchemaUtil.getVarCharLength;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 import java.util.TreeMap;
 
 import org.apache.hadoop.hbase.Cell;
@@ -27,7 +30,6 @@ import org.apache.hadoop.hbase.CellScanner;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.KeyValue;
-import org.apache.hadoop.hbase.client.Get;
 import org.apache.hadoop.hbase.client.HTableInterface;
 import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.client.ResultScanner;
@@ -42,6 +44,7 @@ import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.types.PLong;
 import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.MetaDataUtil;
+
 /**
  * Simple utility class for managing multiple key parts of the statistic
  */
@@ -52,11 +55,10 @@ public class StatisticsUtil {
 
     /** Number of parts in our complex key */
     protected static final int NUM_KEY_PARTS = 3;
-    
 
-    public static byte[] getRowKey(byte[] table, ImmutableBytesPtr fam, byte[] region) {
+    public static byte[] getRowKey(byte[] table, ImmutableBytesPtr fam, byte[] guidePostStartKey) {
         // always starts with the source table
-        byte[] rowKey = new byte[table.length + fam.getLength() + region.length + 2];
+        byte[] rowKey = new byte[table.length + fam.getLength() + guidePostStartKey.length + 2];
         int offset = 0;
         System.arraycopy(table, 0, rowKey, offset, table.length);
         offset += table.length;
@@ -64,87 +66,125 @@ public class StatisticsUtil {
         System.arraycopy(fam.get(), fam.getOffset(), rowKey, offset, fam.getLength());
         offset += fam.getLength();
         rowKey[offset++] = QueryConstants.SEPARATOR_BYTE; // assumes stats table columns not DESC
-        System.arraycopy(region, 0, rowKey, offset, region.length);
+        System.arraycopy(guidePostStartKey, 0, rowKey, offset, guidePostStartKey.length);
+        return rowKey;
+    }
+
+    public static byte[] getKey(byte[] table, ImmutableBytesPtr fam) {
+        // always starts with the source table and column family
+        byte[] rowKey = new byte[table.length + fam.getLength() + 1];
+        int offset = 0;
+        System.arraycopy(table, 0, rowKey, offset, table.length);
+        offset += table.length;
+        rowKey[offset++] = QueryConstants.SEPARATOR_BYTE; // assumes stats table columns not DESC
+        System.arraycopy(fam.get(), fam.getOffset(), rowKey, offset, fam.getLength());
+        offset += fam.getLength();
         return rowKey;
     }
-    
+
     public static byte[] copyRow(KeyValue kv) {
         return Arrays.copyOfRange(kv.getRowArray(), kv.getRowOffset(), kv.getRowOffset() + kv.getRowLength());
     }
 
-    public static Result readRegionStatistics(HTableInterface statsHTable, byte[] tableNameBytes, ImmutableBytesPtr cf, byte[] regionName, long clientTimeStamp)
-            throws IOException {
-        byte[] prefix = StatisticsUtil.getRowKey(tableNameBytes, cf, regionName);
-        Get get = new Get(prefix);
-        get.setTimeRange(MetaDataProtocol.MIN_TABLE_TIMESTAMP, clientTimeStamp);
-        get.addColumn(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, PhoenixDatabaseMetaData.GUIDE_POSTS_WIDTH_BYTES);
-        get.addColumn(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, PhoenixDatabaseMetaData.GUIDE_POSTS_BYTES);
-        get.addColumn(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, PhoenixDatabaseMetaData.GUIDE_POSTS_ROW_COUNT_BYTES);
-        get.addColumn(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES,
-            PhoenixDatabaseMetaData.MIN_KEY_BYTES);
-        return statsHTable.get(get);
+    public static byte[] getAdjustedKey(byte[] key, byte[] tableNameBytes, ImmutableBytesPtr cf, boolean nextKey) {
+        if (Bytes.compareTo(key, ByteUtil.EMPTY_BYTE_ARRAY) != 0) { return getRowKey(tableNameBytes, cf, key); }
+        key = ByteUtil.concat(getKey(tableNameBytes, cf), QueryConstants.SEPARATOR_BYTE_ARRAY);
+        if (nextKey) {
+            ByteUtil.nextKey(key, key.length);
+        }
+        return key;
+    }
+
+    public static List<Result> readStatistics(HTableInterface statsHTable, byte[] tableNameBytes, ImmutableBytesPtr cf,
+            byte[] startKey, byte[] stopKey, long clientTimeStamp) throws IOException {
+        List<Result> statsForRegion = new ArrayList<Result>();
+        Scan s = MetaDataUtil.newTableRowsScan(getAdjustedKey(startKey, tableNameBytes, cf, false),
+                getAdjustedKey(stopKey, tableNameBytes, cf, true), MetaDataProtocol.MIN_TABLE_TIMESTAMP,
+                clientTimeStamp);
+        s.addColumn(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, QueryConstants.EMPTY_COLUMN_BYTES);
+        ResultScanner scanner = null;
+        try {
+            scanner = statsHTable.getScanner(s);
+            Result result = null;
+            while ((result = scanner.next()) != null) {
+                statsForRegion.add(result);
+            }
+        } finally {
+            if (scanner != null) {
+                scanner.close();
+            }
+        }
+        return statsForRegion;
     }
-    
+
     public static PTableStats readStatistics(HTableInterface statsHTable, byte[] tableNameBytes, long clientTimeStamp)
             throws IOException {
         ImmutableBytesWritable ptr = new ImmutableBytesWritable();
         Scan s = MetaDataUtil.newTableRowsScan(tableNameBytes, MetaDataProtocol.MIN_TABLE_TIMESTAMP, clientTimeStamp);
-        s.addColumn(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, PhoenixDatabaseMetaData.GUIDE_POSTS_BYTES);
+        s.addColumn(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, PhoenixDatabaseMetaData.GUIDE_POSTS_WIDTH_BYTES);
         s.addColumn(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, PhoenixDatabaseMetaData.GUIDE_POSTS_ROW_COUNT_BYTES);
-        ResultScanner scanner = statsHTable.getScanner(s);
-        Result result = null;
+        s.addColumn(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, QueryConstants.EMPTY_COLUMN_BYTES);
+        ResultScanner scanner = null;
         long timeStamp = MetaDataProtocol.MIN_TABLE_TIMESTAMP;
-        TreeMap<byte[], GuidePostsInfo> guidePostsPerCf = new TreeMap<byte[], GuidePostsInfo>(
-                Bytes.BYTES_COMPARATOR);
-        while ((result = scanner.next()) != null) {
-            CellScanner cellScanner = result.cellScanner();
-            long rowCount = 0;
-            ImmutableBytesPtr valuePtr = new ImmutableBytesPtr(HConstants.EMPTY_BYTE_ARRAY);
-            byte[] cfName = null;
-            int tableNameLength;
-            int cfOffset;
-            int cfLength;
-            boolean valuesSet = false;
-            // Only the two cells with quals GUIDE_POSTS_ROW_COUNT_BYTES and GUIDE_POSTS_BYTES would be retrieved
-            while (cellScanner.advance()) {
-                Cell current = cellScanner.current();
-                if (!valuesSet) {
-                    tableNameLength = tableNameBytes.length + 1;
-                    cfOffset = current.getRowOffset() + tableNameLength;
-                    cfLength = getVarCharLength(current.getRowArray(), cfOffset, current.getRowLength()
-                            - tableNameLength);
-                    ptr.set(current.getRowArray(), cfOffset, cfLength);
-                    valuesSet = true;
-                }
-                cfName = ByteUtil.copyKeyBytesIfNecessary(ptr);
-                if (Bytes.equals(current.getQualifierArray(), current.getQualifierOffset(),
-                        current.getQualifierLength(), PhoenixDatabaseMetaData.GUIDE_POSTS_ROW_COUNT_BYTES, 0,
-                        PhoenixDatabaseMetaData.GUIDE_POSTS_ROW_COUNT_BYTES.length)) {
-                    rowCount = PLong.INSTANCE.getCodec().decodeLong(current.getValueArray(),
-                            current.getValueOffset(), SortOrder.getDefault());
-                } else {
-                    valuePtr.set(current.getValueArray(), current.getValueOffset(),
-                        current.getValueLength());
+        TreeMap<byte[], GuidePostsInfo> guidePostsPerCf = new TreeMap<byte[], GuidePostsInfo>(Bytes.BYTES_COMPARATOR);
+        try {
+            scanner = statsHTable.getScanner(s);
+            Result result = null;
+            while ((result = scanner.next()) != null) {
+                CellScanner cellScanner = result.cellScanner();
+                long rowCount = 0;
+                long byteCount = 0;
+                byte[] cfName = null;
+                int tableNameLength;
+                int cfOffset;
+                int cfLength;
+                boolean valuesSet = false;
+                // Only the two cells with quals GUIDE_POSTS_ROW_COUNT_BYTES and GUIDE_POSTS_BYTES would be retrieved
+                while (cellScanner.advance()) {
+                    Cell current = cellScanner.current();
+                    if (!valuesSet) {
+                        tableNameLength = tableNameBytes.length + 1;
+                        cfOffset = current.getRowOffset() + tableNameLength;
+                        cfLength = getVarCharLength(current.getRowArray(), cfOffset,
+                                current.getRowLength() - tableNameLength);
+                        ptr.set(current.getRowArray(), cfOffset, cfLength);
+                        valuesSet = true;
+                    }
+                    cfName = ByteUtil.copyKeyBytesIfNecessary(ptr);
+                    if (Bytes.equals(current.getQualifierArray(), current.getQualifierOffset(),
+                            current.getQualifierLength(), PhoenixDatabaseMetaData.GUIDE_POSTS_ROW_COUNT_BYTES, 0,
+                            PhoenixDatabaseMetaData.GUIDE_POSTS_ROW_COUNT_BYTES.length)) {
+                        rowCount = PLong.INSTANCE.getCodec().decodeLong(current.getValueArray(),
+                                current.getValueOffset(), SortOrder.getDefault());
+                    } else if (Bytes.equals(current.getQualifierArray(), current.getQualifierOffset(),
+                            current.getQualifierLength(), PhoenixDatabaseMetaData.GUIDE_POSTS_WIDTH_BYTES, 0,
+                            PhoenixDatabaseMetaData.GUIDE_POSTS_WIDTH_BYTES.length)) {
+                        byteCount = PLong.INSTANCE.getCodec().decodeLong(current.getValueArray(),
+                                current.getValueOffset(), SortOrder.getDefault());
+                    }
+                    if (current.getTimestamp() > timeStamp) {
+                        timeStamp = current.getTimestamp();
+                    }
                 }
-                if (current.getTimestamp() > timeStamp) {
-                    timeStamp = current.getTimestamp();
+                if (cfName != null) {
+                    byte[] newGPStartKey = getGuidePostsInfoFromRowKey(tableNameBytes, cfName, result.getRow());
+                    GuidePostsInfo guidePosts = guidePostsPerCf.get(cfName);
+                    if (guidePosts == null) {
+                        guidePosts = new GuidePostsInfo(0l, Collections.<byte[]> emptyList(), 0l);
+                        guidePostsPerCf.put(cfName, guidePosts);
+                    }
+                    guidePosts.addGuidePost(newGPStartKey, byteCount, rowCount);
                 }
             }
-            if (cfName != null) {
-                GuidePostsInfo newGPInfo = GuidePostsInfo.deserializeGuidePostsInfo(
-                        valuePtr.get(), valuePtr.getOffset(), valuePtr.getLength(), rowCount);
-                GuidePostsInfo oldInfo = guidePostsPerCf.put(cfName, newGPInfo);
-                if (oldInfo != null) {
-                    newGPInfo.combine(oldInfo);
-                }
+        } finally {
+            if (scanner != null) {
+                scanner.close();
             }
         }
-        if (!guidePostsPerCf.isEmpty()) {
-            return new PTableStatsImpl(guidePostsPerCf, timeStamp);
-        }
+        if (!guidePostsPerCf.isEmpty()) { return new PTableStatsImpl(guidePostsPerCf, timeStamp); }
         return PTableStats.EMPTY_STATS;
     }
-    
+
     public static long getGuidePostDepth(int guidepostPerRegion, long guidepostWidth, HTableDescriptor tableDesc) {
         if (guidepostPerRegion > 0) {
             long maxFileSize = HConstants.DEFAULT_MAX_FILE_SIZE;
@@ -159,4 +199,11 @@ public class StatisticsUtil {
             return guidepostWidth;
         }
     }
+
+	public static byte[] getGuidePostsInfoFromRowKey(byte[] tableNameBytes, byte[] fam, byte[] row) {
+		ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+		int gpOffset = tableNameBytes.length + 1 + fam.length + 1;
+		ptr.set(row, gpOffset, row.length - gpOffset);
+		return ByteUtil.copyKeyBytesIfNecessary(ptr);
+	}
 }
\ No newline at end of file


Mime
View raw message