Repository: phoenix Updated Branches: refs/heads/3.0 a5b797225 -> 75484fb32
Phoenix-1333 Store statistics guideposts as VARBINARY (Ramkrishna S Vasudevan) Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/75484fb3 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/75484fb3 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/75484fb3 Branch: refs/heads/3.0 Commit: 75484fb32ae73954e63f1364cb6652760fefe579 Parents: a5b7972 Author: Ramkrishna <ramkrishna.s.vasude...@intel.com> Authored: Mon Oct 13 11:45:44 2014 +0530 Committer: Ramkrishna <ramkrishna.s.vasude...@intel.com> Committed: Mon Oct 13 11:45:44 2014 +0530 ---------------------------------------------------------------------- .../org/apache/phoenix/end2end/QueryIT.java | 2 +- .../phoenix/iterate/ParallelIterators.java | 35 ++++-------- .../phoenix/jdbc/PhoenixDatabaseMetaData.java | 4 ++ .../apache/phoenix/query/QueryConstants.java | 6 +- .../org/apache/phoenix/schema/PTableImpl.java | 6 +- .../phoenix/schema/stats/PTableStats.java | 4 +- .../phoenix/schema/stats/PTableStatsImpl.java | 25 ++++---- .../schema/stats/StatisticsCollector.java | 60 +++++++++----------- .../phoenix/schema/stats/StatisticsUtil.java | 31 ++-------- .../phoenix/schema/stats/StatisticsWriter.java | 9 ++- 10 files changed, 80 insertions(+), 102 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/75484fb3/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryIT.java index ac1c61b..7282f39 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryIT.java @@ -282,7 +282,7 @@ public class QueryIT extends BaseQueryIT { upsertConn.close(); String query = "SELECT organization_id, a_string AS a FROM atable WHERE organization_id=? and a_integer = 5"; - props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 20)); + props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); Connection conn = DriverManager.getConnection(getUrl(), props); PreparedStatement statement = conn.prepareStatement(query); statement.setString(1, tenantId); http://git-wip-us.apache.org/repos/asf/phoenix/blob/75484fb3/phoenix-core/src/main/java/org/apache/phoenix/iterate/ParallelIterators.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ParallelIterators.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ParallelIterators.java index c8c2dba..e4fb0ed 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/ParallelIterators.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/ParallelIterators.java @@ -60,6 +60,7 @@ import org.apache.phoenix.schema.PTable.ViewType; import org.apache.phoenix.schema.SaltingUtil; import org.apache.phoenix.schema.StaleRegionBoundaryCacheException; import org.apache.phoenix.schema.TableRef; +import org.apache.phoenix.schema.stats.GuidePostsInfo; import org.apache.phoenix.schema.stats.PTableStats; import org.apache.phoenix.util.ByteUtil; import org.apache.phoenix.util.ReadOnlyProps; @@ -115,27 +116,8 @@ public class ParallelIterators extends ExplainTable implements ResultIterators { PTable table = tableRef.getTable(); FilterableStatement statement = plan.getStatement(); RowProjector projector = plan.getProjector(); - MetaDataClient client = new MetaDataClient(context.getConnection()); physicalTableName = table.getPhysicalName().getBytes(); tableStats = useStats() ? new MetaDataClient(context.getConnection()).getTableStats(table) : PTableStats.EMPTY_STATS; -/* PTable physicalTable = tableRef.getTable(); - String physicalName = tableRef.getTable().getPhysicalName().getString(); - if ((physicalTable.getViewIndexId() == null) && (!physicalName.equals(physicalTable.getName().getString()))) { // tableRef is not for the physical table - String physicalSchemaName = SchemaUtil.getSchemaNameFromFullName(physicalName); - String physicalTableName = SchemaUtil.getTableNameFromFullName(physicalName); - // TODO: this will be an extra RPC to ensure we have the latest guideposts, but is almost always - // unnecessary. We should instead track when the last time an update cache was done for this - // for physical table and not do it again until some interval has passed (it's ok to use stale stats). - MetaDataMutationResult result = client.updateCache(null, use global tenant id to get physical table - physicalSchemaName, physicalTableName); - physicalTable = result.getTable(); - if(physicalTable == null) { - client = new MetaDataClient(context.getConnection()); - physicalTable = client.getConnection().getMetaDataCache() - .getTable(new PTableKey(null, physicalTableName)); - } - } - this.physicalTable = physicalTable;*/ Scan scan = context.getScan(); if (projector.isProjectEmptyKeyValue()) { Map<byte [], NavigableSet<byte []>> familyMap = scan.getFamilyMap(); @@ -329,19 +311,26 @@ public class ParallelIterators extends ExplainTable implements ResultIterators { List<byte[]> gps = null; PTable table = getTable(); - Map<byte[],List<byte[]>> guidePostMap = tableStats.getGuidePosts(); + Map<byte[],GuidePostsInfo> guidePostMap = tableStats.getGuidePosts(); byte[] defaultCF = SchemaUtil.getEmptyColumnFamily(getTable()); if (table.getColumnFamilies().isEmpty()) { // For sure we can get the defaultCF from the table - gps = guidePostMap.get(defaultCF); + if (guidePostMap.get(defaultCF) != null) { + gps = guidePostMap.get(defaultCF).getGuidePosts(); + } } else { Scan scan = context.getScan(); if (scan.getFamilyMap().size() > 0 && !scan.getFamilyMap().containsKey(defaultCF)) { // If default CF is not used in scan, use first CF referenced in scan - gps = guidePostMap.get(scan.getFamilyMap().keySet().iterator().next()); + GuidePostsInfo guidePostsInfo = guidePostMap.get(scan.getFamilyMap().keySet().iterator().next()); + if (guidePostsInfo != null) { + gps = guidePostsInfo.getGuidePosts(); + } } else { // Otherwise, favor use of default CF. - gps = guidePostMap.get(defaultCF); + if (guidePostMap.get(defaultCF) != null) { + gps = guidePostMap.get(defaultCF).getGuidePosts(); + } } } if (gps == null) { http://git-wip-us.apache.org/repos/asf/phoenix/blob/75484fb3/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 ad92c3b..84392c0 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 @@ -231,6 +231,10 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho public static final byte[] REGION_NAME_BYTES = Bytes.toBytes(REGION_NAME); public static final String GUIDE_POSTS = "GUIDE_POSTS"; public static final byte[] GUIDE_POSTS_BYTES = Bytes.toBytes(GUIDE_POSTS); + public static final String GUIDE_POSTS_COUNT = "GUIDE_POSTS_COUNT"; + public static final byte[] GUIDE_POSTS_COUNT_BYTES = Bytes.toBytes(GUIDE_POSTS_COUNT); + public static final String GUIDE_POSTS_WIDTH = "GUIDE_POSTS_WIDTH"; + public static final byte[] GUIDE_POSTS_WIDTH_BYTES = Bytes.toBytes(GUIDE_POSTS_WIDTH); public static final String MIN_KEY = "MIN_KEY"; public static final byte[] MIN_KEY_BYTES = Bytes.toBytes(MIN_KEY); public static final String MAX_KEY = "MAX_KEY"; http://git-wip-us.apache.org/repos/asf/phoenix/blob/75484fb3/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 f4cf135..b26b426 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 @@ -35,6 +35,8 @@ import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.DECIMAL_DIGITS; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.DEFAULT_COLUMN_FAMILY_NAME; import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.DISABLE_WAL; 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_WIDTH; 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; @@ -235,7 +237,9 @@ public interface QueryConstants { PHYSICAL_NAME + " VARCHAR NOT NULL," + COLUMN_FAMILY + " VARCHAR," + REGION_NAME + " VARCHAR," + - GUIDE_POSTS + " VARBINARY[]," + + GUIDE_POSTS_COUNT + " BIGINT," + + GUIDE_POSTS + " VARBINARY," + + GUIDE_POSTS_WIDTH + " BIGINT," + MIN_KEY + " VARBINARY," + MAX_KEY + " VARBINARY," + LAST_STATS_UPDATE_TIME+ " DATE, "+ http://git-wip-us.apache.org/repos/asf/phoenix/blob/75484fb3/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java index 007abd2..6733511 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java @@ -45,6 +45,7 @@ import org.apache.phoenix.hbase.index.util.KeyValueBuilder; import org.apache.phoenix.index.IndexMaintainer; import org.apache.phoenix.query.QueryConstants; import org.apache.phoenix.schema.RowKeySchema.RowKeySchemaBuilder; +import org.apache.phoenix.schema.stats.GuidePostsInfo; import org.apache.phoenix.schema.stats.PTableStats; import org.apache.phoenix.schema.stats.PTableStatsImpl; import org.apache.phoenix.util.ByteUtil; @@ -375,7 +376,8 @@ public class PTableImpl implements PTable { } this.parentTableName = parentTableName; - this.parentName = parentTableName == null ? null : PNameFactory.newName(SchemaUtil.getTableName(schemaName.getString(), parentTableName.getString())); + this.parentName = parentTableName == null ? null : PNameFactory.newName(SchemaUtil.getTableName( + schemaName.getString(), parentTableName.getString())); estimatedSize += PNameFactory.getEstimatedSize(this.parentName); this.physicalNames = physicalNames == null ? ImmutableList.<PName>of() : ImmutableList.copyOf(physicalNames); @@ -705,7 +707,7 @@ public class PTableImpl implements PTable { public long getTimeStamp() { return timeStamp; } - + @Override public void readFields(DataInput input) throws IOException { byte[] tenantIdBytes = Bytes.readByteArray(input); http://git-wip-us.apache.org/repos/asf/phoenix/blob/75484fb3/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/PTableStats.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/PTableStats.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/PTableStats.java index d902cb9..9719ecf 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/PTableStats.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/PTableStats.java @@ -40,7 +40,7 @@ public interface PTableStats extends Writable { public static final PTableStats EMPTY_STATS = new PTableStats() { @Override - public SortedMap<byte[], List<byte[]>> getGuidePosts() { + public SortedMap<byte[], GuidePostsInfo> getGuidePosts() { return ImmutableSortedMap.of(); } @@ -65,7 +65,7 @@ public interface PTableStats extends Writable { * Returns a tree map of the guide posts collected against a column family * @return */ - SortedMap<byte[], List<byte[]>> getGuidePosts(); + SortedMap<byte[], GuidePostsInfo> getGuidePosts(); int getEstimatedSize(); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/75484fb3/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/PTableStatsImpl.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/PTableStatsImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/PTableStatsImpl.java index 159fb79..fab9f52 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/PTableStatsImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/PTableStatsImpl.java @@ -38,20 +38,20 @@ import com.sun.istack.NotNull; * Implementation for PTableStats */ public class PTableStatsImpl implements PTableStats { - private final SortedMap<byte[], List<byte[]>> guidePosts; + private final SortedMap<byte[], GuidePostsInfo> guidePosts; private final int estimatedSize; public PTableStatsImpl() { - this(new TreeMap<byte[], List<byte[]>>(Bytes.BYTES_COMPARATOR)); + this(new TreeMap<byte[], GuidePostsInfo>(Bytes.BYTES_COMPARATOR)); } - public PTableStatsImpl(@NotNull SortedMap<byte[], List<byte[]>> guidePosts) { + public PTableStatsImpl(@NotNull SortedMap<byte[], GuidePostsInfo> guidePosts) { this.guidePosts = guidePosts; int estimatedSize = SizedUtil.OBJECT_SIZE + SizedUtil.INT_SIZE + SizedUtil.sizeOfTreeMap(guidePosts.size()); - for (Map.Entry<byte[], List<byte[]>> entry : guidePosts.entrySet()) { + for (Map.Entry<byte[], GuidePostsInfo> entry : guidePosts.entrySet()) { byte[] cf = entry.getKey(); estimatedSize += SizedUtil.ARRAY_SIZE + cf.length; - List<byte[]> keys = entry.getValue(); + List<byte[]> keys = entry.getValue().getGuidePosts(); estimatedSize += SizedUtil.sizeOfArrayList(keys.size()); for (byte[] key : keys) { estimatedSize += SizedUtil.ARRAY_SIZE + key.length; @@ -61,16 +61,17 @@ public class PTableStatsImpl implements PTableStats { } @Override - public SortedMap<byte[], List<byte[]>> getGuidePosts() { + public SortedMap<byte[], GuidePostsInfo> getGuidePosts() { return guidePosts; } @Override public void write(DataOutput output) throws IOException { WritableUtils.writeVInt(output, guidePosts.size()); - for (Entry<byte[], List<byte[]>> entry : guidePosts.entrySet()) { + for (Entry<byte[], GuidePostsInfo> entry : guidePosts.entrySet()) { Bytes.writeByteArray(output, entry.getKey()); - List<byte[]> value = entry.getValue(); + List<byte[]> value = entry.getValue().getGuidePosts(); + output.writeLong(entry.getValue().getByteCount()); WritableUtils.writeVInt(output, value.size()); for (int i = 0; i < value.size(); i++) { Bytes.writeByteArray(output, value.get(i)); @@ -83,12 +84,13 @@ public class PTableStatsImpl implements PTableStats { int size = WritableUtils.readVInt(input); for (int i = 0; i < size; i++) { byte[] key = Bytes.readByteArray(input); + long byteCount = input.readLong(); int valueSize = WritableUtils.readVInt(input); List<byte[]> value = Lists.newArrayListWithExpectedSize(valueSize); for (int j = 0; j < valueSize; j++) { value.add(j, Bytes.readByteArray(input)); } - guidePosts.put(key, value); + guidePosts.put(key, new GuidePostsInfo(byteCount, value)); } } @@ -96,10 +98,10 @@ public class PTableStatsImpl implements PTableStats { public String toString() { StringBuilder buf = new StringBuilder(); buf.append("PTableStats ["); - for (Map.Entry<byte[], List<byte[]>> entry : guidePosts.entrySet()) { + for (Map.Entry<byte[], GuidePostsInfo> entry : guidePosts.entrySet()) { buf.append(Bytes.toStringBinary(entry.getKey())); buf.append(":("); - List<byte[]> keys = entry.getValue(); + List<byte[]> keys = entry.getValue().getGuidePosts(); if (!keys.isEmpty()) { for (byte[] key : keys) { buf.append(Bytes.toStringBinary(key)); @@ -117,5 +119,4 @@ public class PTableStatsImpl implements PTableStats { public int getEstimatedSize() { return estimatedSize; } - } http://git-wip-us.apache.org/repos/asf/phoenix/blob/75484fb3/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 29706c7..2e7bfd9 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 @@ -10,17 +10,20 @@ package org.apache.phoenix.schema.stats; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.client.HTableInterface; import org.apache.hadoop.hbase.client.Mutation; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.hadoop.hbase.regionserver.HRegion; import org.apache.hadoop.hbase.regionserver.InternalScanner; import org.apache.hadoop.hbase.regionserver.KeyValueScanner; @@ -34,8 +37,7 @@ import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr; import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData; import org.apache.phoenix.query.QueryServices; import org.apache.phoenix.query.QueryServicesOptions; -import org.apache.phoenix.schema.PDataType; -import org.apache.phoenix.schema.PhoenixArray; +import org.apache.phoenix.util.ByteUtil; import org.apache.phoenix.util.TimeKeeper; import com.google.common.collect.Lists; @@ -53,7 +55,8 @@ public class StatisticsCollector { private Map<String, byte[]> minMap = Maps.newHashMap(); private Map<String, byte[]> maxMap = Maps.newHashMap(); private long guidepostDepth; - private Map<String, Pair<Integer,List<byte[]>>> guidePostsMap = Maps.newHashMap(); + private Map<String, Pair<Long,GuidePostsInfo>> guidePostsMap = Maps.newHashMap(); + // Tracks the bytecount per family if it has reached the guidePostsDepth private Map<ImmutableBytesPtr, Boolean> familyMap = Maps.newHashMap(); protected StatisticsWriter statsTable; // Ensures that either analyze or compaction happens at any point of time. @@ -63,11 +66,15 @@ public class StatisticsCollector { throws IOException { Configuration config = env.getConfiguration(); HTableInterface statsHTable = env.getTable((PhoenixDatabaseMetaData.SYSTEM_STATS_NAME_BYTES)); - guidepostDepth = - config.getLong(QueryServices.STATS_GUIDEPOST_WIDTH_BYTES_ATTRIB, - statsHTable.getTableDescriptor().getMaxFileSize() / - config.getInt(QueryServices.STATS_GUIDEPOST_PER_REGION_ATTRIB, - QueryServicesOptions.DEFAULT_GUIDE_POSTS_PER_REGION)); + long maxFileSize = statsHTable.getTableDescriptor().getMaxFileSize(); + if (maxFileSize <= 0) { // HBase brain dead API doesn't give you the "real" max file size if it's not set... + maxFileSize = HConstants.DEFAULT_MAX_FILE_SIZE; + } + guidepostDepth = config.getLong( + QueryServices.STATS_GUIDEPOST_WIDTH_BYTES_ATTRIB, + maxFileSize + / config.getInt(QueryServices.STATS_GUIDEPOST_PER_REGION_ATTRIB, + QueryServicesOptions.DEFAULT_GUIDE_POSTS_PER_REGION)); // Get the stats table associated with the current table on which the CP is // triggered @@ -262,7 +269,8 @@ public class StatisticsCollector { familyMap.put(new ImmutableBytesPtr(cf), true); String fam = Bytes.toString(cf); - byte[] row = new ImmutableBytesPtr(kv.getBuffer(), kv.getRowOffset(), kv.getRowLength()).copyBytesIfNecessary(); + byte[] row = ByteUtil.copyKeyBytesIfNecessary( + new ImmutableBytesWritable(kv.getBuffer(), kv.getRowOffset(), kv.getRowLength())); if (!minMap.containsKey(fam) && !maxMap.containsKey(fam)) { minMap.put(fam, row); // Ideally the max key also should be added in this case @@ -278,19 +286,17 @@ public class StatisticsCollector { } } // TODO : This can be moved to an interface so that we could collect guide posts in different ways - Pair<Integer,List<byte[]>> gps = guidePostsMap.get(fam); + Pair<Long,GuidePostsInfo> gps = guidePostsMap.get(fam); if (gps == null) { - gps = new Pair<Integer,List<byte[]>>(0, Lists.<byte[]>newArrayList()); + gps = new Pair<Long,GuidePostsInfo>(0L,new GuidePostsInfo(0, Collections.<byte[]>emptyList())); guidePostsMap.put(fam, gps); } - int byteCount = gps.getFirst() + kv.getLength(); + int kvLength = kv.getLength(); + long byteCount = gps.getFirst() + kvLength; gps.setFirst(byteCount); if (byteCount >= guidepostDepth) { - // Prevent dups - List<byte[]> gpsKeys = gps.getSecond(); - if (gpsKeys.isEmpty() || Bytes.compareTo(row, gpsKeys.get(gpsKeys.size()-1)) > 0) { - gpsKeys.add(row); - gps.setFirst(0); // Only reset count when adding guidepost + if (gps.getSecond().addGuidePost(row, byteCount)) { + gps.setFirst(0L); } } } @@ -305,22 +311,10 @@ public class StatisticsCollector { return null; } - public byte[] getGuidePosts(String fam) { - if (!guidePostsMap.isEmpty()) { - Pair<Integer,List<byte[]>> gps = guidePostsMap.get(fam); - if (gps != null) { - List<byte[]> guidePosts = gps.getSecond(); - if (!guidePosts.isEmpty()) { - byte[][] array = new byte[guidePosts.size()][]; - int i = 0; - for (byte[] element : guidePosts) { - array[i] = element; - i++; - } - PhoenixArray phoenixArray = new PhoenixArray(PDataType.VARBINARY, array); - return PDataType.VARBINARY_ARRAY.toBytes(phoenixArray); - } - } + public GuidePostsInfo getGuidePosts(String fam) { + Pair<Long,GuidePostsInfo> pair = guidePostsMap.get(fam); + if (pair != null) { + return pair.getSecond(); } return null; } http://git-wip-us.apache.org/repos/asf/phoenix/blob/75484fb3/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 bd59730..8d7dd00 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,8 +19,6 @@ package org.apache.phoenix.schema.stats; import static org.apache.phoenix.util.SchemaUtil.getVarCharLength; import java.io.IOException; -import java.util.Collections; -import java.util.List; import java.util.TreeMap; import org.apache.hadoop.hbase.KeyValue; @@ -33,12 +31,8 @@ import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.coprocessor.MetaDataProtocol; import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData; import org.apache.phoenix.query.QueryConstants; -import org.apache.phoenix.schema.PDataType; -import org.apache.phoenix.schema.PhoenixArray; import org.apache.phoenix.util.ByteUtil; import org.apache.phoenix.util.MetaDataUtil; - -import com.google.common.collect.Lists; /** * Simple utility class for managing multiple key parts of the statistic */ @@ -71,7 +65,7 @@ public class StatisticsUtil { ResultScanner scanner = statsHTable.getScanner(s); try { Result result = null; - TreeMap<byte[], List<byte[]>> guidePostsPerCf = new TreeMap<byte[], List<byte[]>>(Bytes.BYTES_COMPARATOR); + TreeMap<byte[], GuidePostsInfo> guidePostsPerCf = new TreeMap<byte[], GuidePostsInfo>(Bytes.BYTES_COMPARATOR); while ((result = scanner.next()) != null) { KeyValue current = result.raw()[0]; int tableNameLength = tableNameBytes.length + 1; @@ -79,28 +73,13 @@ public class StatisticsUtil { int cfLength = getVarCharLength(current.getBuffer(), cfOffset, current.getRowLength() - tableNameLength); ptr.set(current.getBuffer(), cfOffset, cfLength); byte[] cfName = ByteUtil.copyKeyBytesIfNecessary(ptr); - PhoenixArray array = (PhoenixArray)PDataType.VARBINARY_ARRAY.toObject(current.getBuffer(), current.getValueOffset(), current - .getValueLength()); - if (array != null && array.getDimensions() != 0) { - List<byte[]> guidePosts = Lists.newArrayListWithExpectedSize(array.getDimensions()); - for (int j = 0; j < array.getDimensions(); j++) { - byte[] gp = array.toBytes(j); - if (gp.length != 0) { - guidePosts.add(gp); - } - } - List<byte[]> gps = guidePostsPerCf.put(cfName, guidePosts); - if (gps != null) { // Add guidepost already there from other regions - guidePosts.addAll(gps); - } + GuidePostsInfo newInfo = GuidePostsInfo.fromBytes(current.getBuffer(), current.getValueOffset(), current.getValueLength()); + GuidePostsInfo oldInfo = guidePostsPerCf.put(cfName, newInfo); + if (oldInfo != null) { + newInfo.combine(oldInfo); } } if (!guidePostsPerCf.isEmpty()) { - // Sort guideposts, as the order above will depend on the order we traverse - // each region's worth of guideposts above. - for (List<byte[]> gps : guidePostsPerCf.values()) { - Collections.sort(gps, Bytes.BYTES_COMPARATOR); - } return new PTableStatsImpl(guidePostsPerCf); } } finally { http://git-wip-us.apache.org/repos/asf/phoenix/blob/75484fb3/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsWriter.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsWriter.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsWriter.java index 5bf39c5..3f391f5 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsWriter.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/stats/StatisticsWriter.java @@ -87,9 +87,14 @@ public class StatisticsWriter implements Closeable { byte[] prefix = StatisticsUtil.getRowKey(tableName, PDataType.VARCHAR.toBytes(fam), PDataType.VARCHAR.toBytes(regionName)); Put put = new Put(prefix); - if (tracker.getGuidePosts(fam) != null) { + GuidePostsInfo gp = tracker.getGuidePosts(fam); + if (gp != null) { + put.add(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, PhoenixDatabaseMetaData.GUIDE_POSTS_COUNT_BYTES, + clientTimeStamp, PDataType.LONG.toBytes((gp.getGuidePosts().size()))); put.add(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, PhoenixDatabaseMetaData.GUIDE_POSTS_BYTES, - clientTimeStamp, (tracker.getGuidePosts(fam))); + clientTimeStamp, PDataType.VARBINARY.toBytes(gp.toBytes())); + put.add(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, PhoenixDatabaseMetaData.GUIDE_POSTS_WIDTH_BYTES, + clientTimeStamp, PDataType.LONG.toBytes(gp.getByteCount())); } put.add(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, PhoenixDatabaseMetaData.MIN_KEY_BYTES, clientTimeStamp, PDataType.VARBINARY.toBytes(tracker.getMinKey(fam)));