use of com.pingcap.tikv.meta.TiIndexInfo in project tispark by pingcap.
the class TiKVScanAnalyzer method buildTiDAGReq.
// Build scan plan picking access path with lowest cost by estimation
public TiDAGRequest buildTiDAGReq(boolean allowIndexScan, boolean useIndexScanFirst, boolean canUseTiKV, boolean canUseTiFlash, List<TiColumnInfo> columnList, List<Expression> conditions, TiTableInfo table, TableStatistics tableStatistics, TiTimestamp ts, TiDAGRequest dagRequest) {
TiKVScanPlan minPlan = null;
if (canUseTiKV) {
minPlan = buildTableScan(conditions, table, tableStatistics);
}
if (canUseTiFlash) {
// it is possible that only TiFlash plan exists due to isolation read.
TiKVScanPlan plan = buildTiFlashScan(columnList, conditions, table, tableStatistics);
if (minPlan == null || plan.getCost() < minPlan.getCost()) {
minPlan = plan;
}
} else if (canUseTiKV && allowIndexScan) {
minPlan.getFilters().forEach(dagRequest::addDowngradeFilter);
if (table.isPartitionEnabled()) {
// disable index scan
} else {
TiKVScanPlan minIndexPlan = null;
double minIndexCost = Double.MAX_VALUE;
for (TiIndexInfo index : table.getIndices()) {
if (table.isCommonHandle() && table.getPrimaryKey().equals(index)) {
continue;
}
if (supportIndexScan(index, table)) {
TiKVScanPlan plan = buildIndexScan(columnList, conditions, index, table, tableStatistics, false);
if (plan.getCost() < minIndexCost) {
minIndexPlan = plan;
minIndexCost = plan.getCost();
}
}
}
if (minIndexPlan != null && (minIndexCost < minPlan.getCost() || useIndexScanFirst)) {
minPlan = minIndexPlan;
}
}
}
if (minPlan == null) {
throw new TiClientInternalException("No valid plan found for table '" + table.getName() + "'");
}
TiStoreType minPlanStoreType = minPlan.getStoreType();
// TiKV should not use CHBlock as Encode Type.
if (minPlanStoreType == TiStoreType.TiKV && dagRequest.getEncodeType() == EncodeType.TypeCHBlock) {
dagRequest.setEncodeType(EncodeType.TypeChunk);
}
// Set DAG Request's store type as minPlan's store type.
dagRequest.setStoreType(minPlanStoreType);
dagRequest.addRanges(minPlan.getKeyRanges());
dagRequest.setPrunedParts(minPlan.getPrunedParts());
dagRequest.addFilters(new ArrayList<>(minPlan.getFilters()));
if (minPlan.isIndexScan()) {
dagRequest.setIndexInfo(minPlan.getIndex());
// need to set isDoubleRead to true for dagRequest in case of double read
dagRequest.setIsDoubleRead(minPlan.isDoubleRead());
}
dagRequest.setTableInfo(table);
dagRequest.setStartTs(ts);
dagRequest.setEstimatedCount(minPlan.getEstimatedRowCount());
return dagRequest;
}
use of com.pingcap.tikv.meta.TiIndexInfo in project tispark by pingcap.
the class TiKVScanAnalyzerTest method buildIndexScanKeyRangeTest.
@Test
public void buildIndexScanKeyRangeTest() {
TiTableInfo table = createTableWithIndex(6, 5);
TiIndexInfo index = table.getIndices().get(0);
Expression eq1 = equal(ColumnRef.create("c1", table), Constant.create(0));
Expression eq2 = lessEqual(ColumnRef.create("c2", table), Constant.create("wtf"));
List<Expression> exprs = ImmutableList.of(eq1);
ScanSpec result = TiKVScanAnalyzer.extractConditions(exprs, table, index);
List<IndexRange> irs = expressionToIndexRanges(result.getPointPredicates(), result.getRangePredicate(), table, index);
TiKVScanAnalyzer scanAnalyzer = new TiKVScanAnalyzer();
Map<Long, List<Coprocessor.KeyRange>> keyRanges = scanAnalyzer.buildIndexScanKeyRange(table, index, irs, null);
assertEquals(keyRanges.size(), 1);
Coprocessor.KeyRange keyRange = keyRanges.get(table.getId()).get(0);
assertEquals(ByteString.copyFrom(new byte[] { 116, -128, 0, 0, 0, 0, 0, 0, 6, 95, 105, -128, 0, 0, 0, 0, 0, 0, 5, 3, -128, 0, 0, 0, 0, 0, 0, 0 }), keyRange.getStart());
assertEquals(ByteString.copyFrom(new byte[] { 116, -128, 0, 0, 0, 0, 0, 0, 6, 95, 105, -128, 0, 0, 0, 0, 0, 0, 5, 3, -128, 0, 0, 0, 0, 0, 0, 1 }), keyRange.getEnd());
exprs = ImmutableList.of(eq1, eq2);
result = TiKVScanAnalyzer.extractConditions(exprs, table, index);
irs = expressionToIndexRanges(result.getPointPredicates(), result.getRangePredicate(), table, index);
keyRanges = scanAnalyzer.buildIndexScanKeyRange(table, index, irs, null);
assertEquals(keyRanges.size(), 1);
keyRange = keyRanges.get(table.getId()).get(0);
assertEquals(ByteString.copyFrom(new byte[] { 116, -128, 0, 0, 0, 0, 0, 0, 6, 95, 105, -128, 0, 0, 0, 0, 0, 0, 5, 3, -128, 0, 0, 0, 0, 0, 0, 0, 0 }), keyRange.getStart());
assertEquals(ByteString.copyFrom(new byte[] { 116, -128, 0, 0, 0, 0, 0, 0, 6, 95, 105, -128, 0, 0, 0, 0, 0, 0, 5, 3, -128, 0, 0, 0, 0, 0, 0, 0, 1, 119, 116, 102, 0, 0, 0, 0, 0, -5 }), keyRange.getEnd());
}
use of com.pingcap.tikv.meta.TiIndexInfo in project tispark by pingcap.
the class TiKVScanAnalyzerTest method extractConditionsWithPrimaryKeyTest.
@Test
public void extractConditionsWithPrimaryKeyTest() {
TiTableInfo table = createTableWithPrefix();
TiIndexInfo index = TiIndexInfo.generateFakePrimaryKeyIndex(table);
requireNonNull(index);
assertEquals(1, index.getIndexColumns().size());
assertEquals("c1", index.getIndexColumns().get(0).getName());
Expression eq1 = equal(ColumnRef.create("c1", table), Constant.create(0, IntegerType.INT));
Expression eq2 = equal(ColumnRef.create("c2", table), Constant.create("test", StringType.VARCHAR));
Expression le1 = lessEqual(ColumnRef.create("c3", table), Constant.create("fxxx", StringType.VARCHAR));
// Last one should be pushed back
Expression eq3 = equal(ColumnRef.create("c4", table), Constant.create("fxxx", StringType.VARCHAR));
List<Expression> exprs = ImmutableList.of(eq1, eq2, le1, eq3);
ScanSpec result = TiKVScanAnalyzer.extractConditions(exprs, table, index);
Set<Expression> baselineSet = ImmutableSet.of(eq2, le1, eq3);
// 3 remains since c2 condition pushed back as well
assertEquals(baselineSet, result.getResidualPredicates());
assertEquals(1, result.getPointPredicates().size());
assertEquals(eq1, result.getPointPredicates().get(0));
assertFalse(result.getRangePredicate().isPresent());
}
use of com.pingcap.tikv.meta.TiIndexInfo in project tispark by pingcap.
the class TableCodecV2 method decodeRow.
protected static Row decodeRow(byte[] value, Handle handle, TiTableInfo tableInfo) {
if (handle == null && tableInfo.isPkHandle()) {
throw new IllegalArgumentException("when pk is handle, handle cannot be null");
}
int colSize = tableInfo.getColumns().size();
// decode bytes to Map<ColumnID, Data>
HashMap<Long, Object> decodedDataMap = new HashMap<>(colSize);
RowV2 rowV2 = RowV2.createNew(value);
TiIndexInfo pk = tableInfo.getPrimaryKey();
if (pk != null) {
List<TiColumnInfo> cols = new ArrayList<>();
for (TiIndexColumn indexColumn : pk.getIndexColumns()) {
TiColumnInfo col = tableInfo.getColumn(indexColumn.getOffset());
cols.add(col);
}
if (tableInfo.isPkHandle()) {
assert cols.size() == 1;
decodedDataMap.put(cols.get(0).getId(), handle.data()[0]);
}
if (tableInfo.isCommonHandle()) {
for (int i = 0; i < cols.size(); i++) {
decodedDataMap.put(cols.get(i).getId(), handle.data()[i]);
}
}
}
for (TiColumnInfo col : tableInfo.getColumns()) {
if (decodedDataMap.containsKey(col.getId())) {
continue;
} else if (col.isPrimaryKey() && tableInfo.isPkHandle()) {
decodedDataMap.put(col.getId(), handle);
continue;
}
RowV2.ColIDSearchResult searchResult = rowV2.findColID(col.getId());
if (searchResult.isNull) {
// current col is null, nothing should be added to decodedMap
continue;
}
if (!searchResult.notFound) {
// corresponding column should be found
assert (searchResult.idx != -1);
byte[] colData = rowV2.getData(searchResult.idx);
Object d = RowDecoderV2.decodeCol(colData, col.getType());
decodedDataMap.put(col.getId(), d);
}
}
Object[] res = new Object[colSize];
// construct Row with Map<ColumnID, Data> & handle
for (int i = 0; i < colSize; i++) {
// skip pk is handle case
TiColumnInfo col = tableInfo.getColumn(i);
res[i] = decodedDataMap.get(col.getId());
}
return ObjectRowImpl.create(res);
}
use of com.pingcap.tikv.meta.TiIndexInfo in project tispark by pingcap.
the class TiKVScanAnalyzer method isCoveringIndex.
// If all the columns requested in the select list of query, are available in the index, then the
// query engine doesn't have to lookup the table again compared with double read.
boolean isCoveringIndex(List<TiColumnInfo> columns, TiIndexInfo indexColumns, boolean pkIsHandle) {
if (columns.isEmpty()) {
return false;
}
Map<String, TiIndexColumn> colInIndex = indexColumns.getIndexColumns().stream().collect(Collectors.toMap(TiIndexColumn::getName, col -> col));
for (TiColumnInfo colInfo : columns) {
if (pkIsHandle && colInfo.isPrimaryKey()) {
continue;
}
if (colInfo.getId() == -1) {
continue;
}
boolean colNotInIndex = false;
if (colInIndex.containsKey(colInfo.getName())) {
TiIndexColumn indexCol = colInIndex.get(colInfo.getName());
boolean isFullLength = indexCol.isLengthUnspecified() || indexCol.getLength() == colInfo.getType().getLength();
if (!colInfo.getName().equalsIgnoreCase(indexCol.getName()) || !isFullLength) {
colNotInIndex = true;
}
} else {
colNotInIndex = true;
}
if (colNotInIndex) {
return false;
}
}
return true;
}
Aggregations