Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,44 @@ private void testOptimization(String dataTableName, String dataTableFullName, St
assertEquals(4, rs.getInt("k3"));
assertEquals("z", rs.getString("V1"));
assertFalse(rs.next());


//Same as above, but with SKIP-SCAN-JOIN hint
query = "SELECT /*+ INDEX(" + dataTableName + " " + indexTableName + "), NO_INDEX_SERVER_MERGE */ t_id, k1, k2, k3, V1 from " + dataTableFullName + " where v1<='z' and k3 > 1 order by V1,t_id";
rs = conn1.createStatement().executeQuery("EXPLAIN " + query);
expected =
"CLIENT PARALLEL 1-WAY FULL SCAN OVER " + dataTableName + "\n"
+ " SERVER FILTER BY K3 > 1\n"
+ " SERVER SORTED BY \\[" + dataTableName + "\\.V1, " + dataTableName + "\\.T_ID\\]\n"
+ "CLIENT MERGE SORT\n"
+ " SKIP-SCAN-JOIN TABLE 0\n"
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + indexTableName + " \\[\\*\\] - \\['z'\\]\n"
+ " SERVER FILTER BY FIRST KEY ONLY\n"
+ " DYNAMIC SERVER FILTER BY \\(\"" + dataTableName + "\\.T_ID\", \"" + dataTableName + "\\.K1\", \"" + dataTableName + "\\.K2\"\\) IN \\(\\(\\$\\d+\\.\\$\\d+, \\$\\d+\\.\\$\\d+, \\$\\d+\\.\\$\\d+\\)\\)";
actual = QueryUtil.getExplainPlan(rs);
assertTrue("Expected:\n" + expected + "\nbut got\n" + actual, Pattern.matches(expected, actual));


rs = conn1.createStatement().executeQuery(query);
assertTrue(rs.next());
assertEquals("f", rs.getString("t_id"));
assertEquals(1, rs.getInt("k1"));
assertEquals(2, rs.getInt("k2"));
assertEquals(3, rs.getInt("k3"));
assertEquals("a", rs.getString("V1"));
assertTrue(rs.next());
assertEquals("j", rs.getString("t_id"));
assertEquals(2, rs.getInt("k1"));
assertEquals(4, rs.getInt("k2"));
assertEquals(2, rs.getInt("k3"));
assertEquals("a", rs.getString("V1"));
assertTrue(rs.next());
assertEquals("b", rs.getString("t_id"));
assertEquals(1, rs.getInt("k1"));
assertEquals(2, rs.getInt("k2"));
assertEquals(4, rs.getInt("k3"));
assertEquals("z", rs.getString("V1"));
assertFalse(rs.next());

query = "SELECT /*+ INDEX(" + dataTableName + " " + indexTableName + ")*/ t_id, V1, k3 from " + dataTableFullName + " where v1 <='z' group by v1,t_id, k3";
rs = conn1.createStatement().executeQuery("EXPLAIN " + query);
expected =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,16 @@ private QueryPlan addPlan(PhoenixStatement statement, SelectStatement select, PT
if (indexState == PIndexState.ACTIVE || indexState == PIndexState.PENDING_ACTIVE
|| (indexState == PIndexState.PENDING_DISABLE && isUnderPendingDisableThreshold(indexTableRef.getCurrentTime(), indexTable.getIndexDisableTimestamp()))) {
try {
if (select.getHint().hasHint(HintNode.Hint.NO_INDEX_SERVER_MERGE)) {
String schemaNameStr = index.getSchemaName() == null ? null
: index.getSchemaName().getString();
String tableNameStr = index.getTableName() == null ? null
: index.getTableName().getString();
throw new ColumnNotFoundException(schemaNameStr, tableNameStr, null, "*");
}
// translate nodes that match expressions that are indexed to the associated column parse node
indexSelect = ParseNodeRewriter.rewrite(indexSelect, new IndexExpressionParseNodeRewriter(index, null, statement.getConnection(), indexSelect.getUdfParseNodes()));
QueryCompiler compiler = new QueryCompiler(statement, indexSelect, resolver, targetColumns, parallelIteratorFactory, dataPlan.getContext().getSequenceManager(), isProjected, true, dataPlans);
SelectStatement rewrittenIndexSelect = ParseNodeRewriter.rewrite(indexSelect, new IndexExpressionParseNodeRewriter(index, null, statement.getConnection(), indexSelect.getUdfParseNodes()));
QueryCompiler compiler = new QueryCompiler(statement, rewrittenIndexSelect, resolver, targetColumns, parallelIteratorFactory, dataPlan.getContext().getSequenceManager(), isProjected, true, dataPlans);

QueryPlan plan = compiler.compile();
if (indexTable.getIndexType() == IndexType.UNCOVERED_GLOBAL) {
Expand Down Expand Up @@ -377,10 +384,10 @@ && isUnderPendingDisableThreshold(indexTableRef.getCurrentTime(),
if (plan.getProjector().getColumnCount() == nColumns) {
return plan;
} else {
String schemaNameStr = index.getSchemaName()==null? null
String schemaNameStr = index.getSchemaName() == null ? null
: index.getSchemaName().getString();
String tableNameStr = index.getTableName()==null? null
:index.getTableName().getString();
String tableNameStr = index.getTableName() == null ? null
: index.getTableName().getString();
throw new ColumnNotFoundException(schemaNameStr, tableNameStr, null, "*");
}
}
Expand All @@ -391,6 +398,10 @@ && isUnderPendingDisableThreshold(indexTableRef.getCurrentTime(),
* otherwise we just don't use this index (as opposed to trying to join back from
* the index table to the data table.
*/
// Reset the state changes from the attempt above
indexTableRef.setHinted(false);
dataPlan.getContext().setUncoveredIndex(false);

SelectStatement dataSelect = (SelectStatement)dataPlan.getStatement();
ParseNode where = dataSelect.getWhere();
if (isHinted && where != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ public enum Hint {
* Issue https://issues.apache.org/jira/browse/PHOENIX-4751.
*/
HASH_AGGREGATE,
/**
* Do not use server merge for hinted uncovered indexes
*/
NO_INDEX_SERVER_MERGE
};

private final Map<Hint,String> hints;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7008,4 +7008,39 @@ public void testUncoveredPhoenix6969() throws Exception {
}
}

@Test
public void testUncoveredPhoenix6984() throws Exception {
try (Connection conn = DriverManager.getConnection(getUrl());
Statement stmt = conn.createStatement()) {
stmt.execute("CREATE TABLE D (\n" + "K1 CHAR(6) NOT NULL,\n"
+ "K2 VARCHAR(22) NOT NULL,\n"
+ "K3 CHAR(2) NOT NULL,\n"
+ "K4 VARCHAR(36) NOT NULL,\n"
+ "V1 TIMESTAMP,\n"
+ "V2 TIMESTAMP,\n"
+ "CONSTRAINT PK_BILLING_ORDER PRIMARY KEY (K1,K2,K3,K4))");

stmt.execute("CREATE INDEX I ON D(K2, K1, K3, K4)");
String query =
"SELECT /*+ INDEX(D I), NO_INDEX_SERVER_MERGE */ * "
+ "FROM D "
+ "WHERE K2 = 'XXX' AND "
+ "V2 >= TIMESTAMP '2023-05-31 23:59:59.000' AND "
+ "V1 <= TIMESTAMP '2023-04-01 00:00:00.000' "
+ "ORDER BY V2 asc";
ResultSet rs = stmt.executeQuery("EXPLAIN " + query);
String explainPlan = QueryUtil.getExplainPlan(rs);
assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER D\n"
+ " SERVER FILTER BY (V2 >= TIMESTAMP '2023-05-31 23:59:59.000'"
+ " AND V1 <= TIMESTAMP '2023-04-01 00:00:00.000')\n"
+ " SERVER SORTED BY [D.V2]\n"
+ "CLIENT MERGE SORT\n"
+ " SKIP-SCAN-JOIN TABLE 0\n"
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER I ['XXX']\n"
+ " SERVER FILTER BY FIRST KEY ONLY\n"
+ " DYNAMIC SERVER FILTER BY (\"D.K1\", \"D.K2\", \"D.K3\", \"D.K4\")"
+ " IN (($2.$4, $2.$5, $2.$6, $2.$7))",
explainPlan);
}
}
}