This is an automated email from the ASF dual-hosted git repository.
stoty pushed a commit to branch 5.1
in repository https://gitbox.apache.org/repos/asf/phoenix.git
The following commit(s) were added to refs/heads/5.1 by this push:
new de97d19052 PHOENIX-6983 Add hint to disable server merges for
uncovered index queries
de97d19052 is described below
commit de97d19052a1ad6db2b4dce79bcff25332f4de03
Author: Istvan Toth <[email protected]>
AuthorDate: Mon Jun 19 20:13:10 2023 +0200
PHOENIX-6983 Add hint to disable server merges for uncovered index queries
---
.../end2end/index/GlobalIndexOptimizationIT.java | 39 +++++++++++++++++++++-
.../apache/phoenix/optimize/QueryOptimizer.java | 23 ++++++++++---
.../java/org/apache/phoenix/parse/HintNode.java | 4 +++
.../apache/phoenix/compile/QueryCompilerTest.java | 20 +++++++----
4 files changed, 74 insertions(+), 12 deletions(-)
diff --git
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalIndexOptimizationIT.java
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalIndexOptimizationIT.java
index 99f5997a6e..7df45185f0 100644
---
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalIndexOptimizationIT.java
+++
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalIndexOptimizationIT.java
@@ -257,7 +257,44 @@ public class GlobalIndexOptimizationIT extends
ParallelStatsDisabledIT {
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 =
diff --git
a/phoenix-core/src/main/java/org/apache/phoenix/optimize/QueryOptimizer.java
b/phoenix-core/src/main/java/org/apache/phoenix/optimize/QueryOptimizer.java
index d2eee0caaf..68d70e0cb3 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/optimize/QueryOptimizer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/optimize/QueryOptimizer.java
@@ -341,9 +341,22 @@ public class QueryOptimizer {
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
- 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);
+ 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();
@@ -357,8 +370,10 @@ public class QueryOptimizer {
if (plan.getProjector().getColumnCount() == nColumns) {
return plan;
} else if (index.getIndexType() == IndexType.GLOBAL) {
- String schemaNameStr =
index.getSchemaName()==null?null:index.getSchemaName().getString();
- String tableNameStr =
index.getTableName()==null?null:index.getTableName().getString();
+ String schemaNameStr = index.getSchemaName() == null ?
null
+ : index.getSchemaName().getString();
+ String tableNameStr = index.getTableName() == null ?
null
+ : index.getTableName().getString();
throw new ColumnNotFoundException(schemaNameStr,
tableNameStr, null, "*");
}
}
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/HintNode.java
b/phoenix-core/src/main/java/org/apache/phoenix/parse/HintNode.java
index 60334ac3d3..baba60bc91 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/HintNode.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/HintNode.java
@@ -118,6 +118,10 @@ public class HintNode {
* 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;
diff --git
a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
index 7d6a9ec3f4..29dc819270 100644
---
a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
+++
b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
@@ -7024,30 +7024,36 @@ public class QueryCompilerTest extends
BaseConnectionlessQueryTest {
@Test
public void testUncoveredPhoenix6984() throws Exception {
- // This only triggers with PHOENIX-6959
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"
+ + "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) */ * " + "FROM D " + "WHERE " + "K2
= 'XXX' AND "
+ "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";
+ + "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"
+ + " 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 (($3.$5, $3.$6, $3.$7, $3.$8))",
+ + " IN (($2.$4, $2.$5, $2.$6, $2.$7))",
explainPlan);
}
}