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 <st...@apache.org>
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);
         }
     }

Reply via email to