Hi,
This was something I noticed when applying Phoenix table stats into
Calcite-Phoenix cost calculation: When executing the following code (a
slightly modified version of the existing StatisticsUtil method) to scan
stats table for a specific column-family and a specific start/stop key
range, I got guidepost rows that did not contain the rowCount or byteCount
cell, for all rows in the specified range. Apparently, I had set the
corresponding columns in the Scan (as shown below). Meanwhile, another
range of stats in the same table gave me the right result. I am wondering
if this is an expected behavior or it is a bug?
public static PTableStats readStatistics(HTableInterface statsHTable,
byte[] tableNameBytes, ImmutableBytesPtr cf, byte[] startKey,
byte[] stopKey,
long clientTimeStamp)
throws IOException {
ImmutableBytesWritable ptr = new ImmutableBytesWritable();
Scan s;
if (cf == null) {
s = MetaDataUtil.newTableRowsScan(tableNameBytes,
MetaDataProtocol.MIN_TABLE_TIMESTAMP, clientTimeStamp);
} else {
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,
PhoenixDatabaseMetaData.GUIDE_POSTS_WIDTH_BYTES);
s.addColumn(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES,
PhoenixDatabaseMetaData.GUIDE_POSTS_ROW_COUNT_BYTES);
s.addColumn(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES,
QueryConstants.EMPTY_COLUMN_BYTES);
ResultScanner scanner = null;
long timeStamp = MetaDataProtocol.MIN_TABLE_TIMESTAMP;
TreeMap<byte[], GuidePostsInfoBuilder> guidePostsInfoWriterPerCf =
new TreeMap<byte[], GuidePostsInfoBuilder>(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 (cfName != null) {
byte[] newGPStartKey = getGuidePostsInfoFromRowKey(
tableNameBytes, cfName, result.getRow());
GuidePostsInfoBuilder guidePostsInfoWriter =
guidePostsInfoWriterPerCf.get(cfName);
if (guidePostsInfoWriter == null) {
guidePostsInfoWriter = new GuidePostsInfoBuilder();
guidePostsInfoWriterPerCf.put(cfName,
guidePostsInfoWriter);
}
guidePostsInfoWriter.addGuidePosts(newGPStartKey,
byteCount, rowCount);
}
}
if (!guidePostsInfoWriterPerCf.isEmpty()) { return new
PTableStatsImpl(
getGuidePostsPerCf(guidePostsInfoWriterPerCf), timeStamp);
}
} finally {
if (scanner != null) {
scanner.close();
}
}
return PTableStats.EMPTY_STATS;
}