public void testSingleSitedCostModel() throws Exception {
Database clone_db = CatalogCloner.cloneDatabase(catalog_db);
CatalogContext clone_catalogContext = new CatalogContext(clone_db.getCatalog());
info = this.generateInfo(clone_catalogContext);
SingleSitedCostModel costModel = new SingleSitedCostModel(clone_catalogContext);
costModel.setCachingEnabled(true);
Table catalog_tbl = this.getTable(clone_db, TM1Constants.TABLENAME_SUBSCRIBER);
Column target_col = this.getColumn(catalog_tbl, "S_ID");
Collection<VerticalPartitionColumn> candidates = VerticalPartitionerUtil.generateCandidates(target_col, info.stats);
assertNotNull(candidates);
assertFalse(candidates.isEmpty());
VerticalPartitionColumn vpc = CollectionUtil.first(candidates);
assertNotNull(vpc);
assertFalse(vpc.isUpdateApplied());
// Create a filter that only has the procedures that will be optimized by our VerticalPartitionColumn
ProcedureNameFilter filter = new ProcedureNameFilter(false);
for (Statement catalog_stmt : vpc.getOptimizedQueries()) {
filter.include(catalog_stmt.getParent().getName(), 1);
} // FOR
// Calculate the cost *BEFORE* applying the vertical partition optimization
double expected_cost = costModel.estimateWorkloadCost(clone_catalogContext, workload, filter, null);
System.err.println("ORIGINAL COST: " + expected_cost);
Map<Long, TransactionCacheEntry> expected_entries = new HashMap<Long, TransactionCacheEntry>();
for (TransactionCacheEntry txn_entry : costModel.getTransactionCacheEntries()) {
// There should be no unknown queries and all transactions should be multi-sited
assertEquals(txn_entry.toString(), 0, txn_entry.getUnknownQueryCount());
assertFalse(txn_entry.isSinglePartitioned());
TransactionCacheEntry clone = (TransactionCacheEntry)txn_entry.clone();
assertNotSame(txn_entry, clone);
expected_entries.put(txn_entry.getTransactionId(), clone);
// System.err.println(StringUtil.columns(txn_entry.debug(), clone.debug()));
// System.err.println(StringUtil.SINGLE_LINE);
} // FOR
assertFalse(expected_entries.isEmpty());
for (Statement catalog_stmt : vpc.getOptimizedQueries()) {
Collection<QueryCacheEntry> entries = costModel.getQueryCacheEntries(catalog_stmt);
assertNotNull(entries);
assertFalse(entries.isEmpty());
} // FOR
// Now apply the update and get the new cost. We don't care what the cost
// is because SingleSitedCostModel only looks to see whether a txn is single-partition
// and not how many partition it actually touches
// We have to clear the cache for these queries first though
vpc.applyUpdate();
costModel.invalidateCache(vpc.getOptimizedQueries());
double new_cost = costModel.estimateWorkloadCost(clone_catalogContext, workload, filter, null);
System.err.println("NEW COST: " + new_cost);
Collection<TransactionCacheEntry> new_entries = costModel.getTransactionCacheEntries();
assertNotNull(new_entries);
assertEquals(expected_entries.size(), new_entries.size());
for (TransactionCacheEntry txn_entry : costModel.getTransactionCacheEntries()) {
TransactionCacheEntry expected = expected_entries.get(txn_entry.getTransactionId());
assertNotNull(expected);
assertEquals(expected.getUnknownQueryCount(), txn_entry.getUnknownQueryCount());
assertEquals(expected.getExaminedQueryCount(), txn_entry.getExaminedQueryCount());
assertEquals(expected.getTotalQueryCount(), txn_entry.getTotalQueryCount());
assertEquals(expected.getExecutionPartition(), txn_entry.getExecutionPartition());
assertThat(expected.getMultiSiteQueryCount(), not(equalTo(txn_entry.getMultiSiteQueryCount())));
assertThat(expected.getSingleSiteQueryCount(), not(equalTo(txn_entry.getSingleSiteQueryCount())));
// None of the queries should touch all of the partitions
for (QueryCacheEntry query_entry : costModel.getQueryCacheEntries(txn_entry.getTransactionId())) {
assertNotNull(query_entry);
assertFalse(query_entry.isInvalid());
assertFalse(query_entry.isUnknown());
assertEquals(1, query_entry.getAllPartitions().size());
} // FOR