PHOENIX-2681 Avoid usage of HashSet<byte[]> in guideposts selection

Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/18f7a694
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/18f7a694
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/18f7a694

Branch: refs/heads/calcite
Commit: 18f7a69452eec7fd5fde38953510600c4a060151
Parents: decbfe3
Author: James Taylor <jtay...@salesforce.com>
Authored: Thu Feb 11 20:09:16 2016 -0800
Committer: James Taylor <jtay...@salesforce.com>
Committed: Thu Feb 11 20:14:31 2016 -0800

----------------------------------------------------------------------
 .../phoenix/end2end/MultiCfQueryExecIT.java     | 51 ++++++++++++++++++++
 .../phoenix/iterate/BaseResultIterators.java    | 35 ++++++--------
 2 files changed, 66 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/18f7a694/phoenix-core/src/it/java/org/apache/phoenix/end2end/MultiCfQueryExecIT.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/MultiCfQueryExecIT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/MultiCfQueryExecIT.java
index f5566ce..2b14fe9 100644
--- 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/MultiCfQueryExecIT.java
+++ 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/MultiCfQueryExecIT.java
@@ -52,6 +52,7 @@ public class MultiCfQueryExecIT extends 
BaseOwnClusterClientManagedTimeIT {
         Map<String,String> props = Maps.newHashMapWithExpectedSize(3);
         // Must update config before starting server
         props.put(QueryServices.STATS_GUIDEPOST_WIDTH_BYTES_ATTRIB, 
Long.toString(20));
+        props.put(QueryServices.QUEUE_SIZE_ATTRIB, Long.toString(200));
         setUpTestDriver(new ReadOnlyProps(props.entrySet().iterator()));
     }
     
@@ -184,6 +185,56 @@ public class MultiCfQueryExecIT extends 
BaseOwnClusterClientManagedTimeIT {
     }
 
     @Test
+    public void testGuidePostsForMultiCFsOverUnevenDistrib() throws Exception {
+        long ts = nextTimestamp();
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts 
+ 10));
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        
+        conn.createStatement().execute("CREATE TABLE T_6CF (K1 CHAR(1) NOT 
NULL, "
+                + "K2 VARCHAR NOT NULL, "
+                + "CF1.A INTEGER, "
+                + "CF2.B INTEGER, "
+                + "CF3.C INTEGER, "
+                + "CF4.D INTEGER, "
+                + "CF5.E INTEGER, "
+                + "CF6.F INTEGER "
+                + "CONSTRAINT PK PRIMARY KEY (K1,K2)) SPLIT ON ('B','C','D')");
+
+        conn.close();
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts 
+ 20));
+        conn = DriverManager.getConnection(getUrl(), props);
+        for (int i = 0; i < 100; i++) {
+            String upsert = "UPSERT INTO T_6CF(K1,K2,A) VALUES('" + 
Character.toString((char)('A'+i%10)) + "','" + (i*10) + "'," + i + ")";
+            conn.createStatement().execute(upsert);
+            if (i % 10 == 0) {
+                conn.createStatement().execute("UPSERT INTO T_6CF(K1,K2,F) 
VALUES('" + Character.toString((char)('A'+i%10)) + "','" + (i*10) + "'," + (i * 
10) + ")");
+            }
+        }
+        conn.commit();
+        conn.close();
+        
+        props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts 
+ 40));
+        conn = DriverManager.getConnection(getUrl(), props);
+        try {
+            analyzeTable(getUrl(), ts + 30, "T_6CF");
+            PreparedStatement statement = conn.prepareStatement("select 
count(*) from T_6CF where f < 400");
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            assertEquals(4, rs.getLong(1));
+            assertFalse(rs.next());
+            List<KeyRange> splits = getAllSplits(conn, "T_6CF", "f < 400", 
"COUNT(*)");
+            // Uses less populated column f
+            assertEquals(14, splits.size());
+            // Uses more populated column a
+            splits = getAllSplits(conn, "T_6CF", "a < 80", "COUNT(*)");
+            assertEquals(104, splits.size());
+        } finally {
+            conn.close();
+        }
+    }
+
+    @Test
     public void testGuidePostsRetrievedForMultiCF() throws Exception {
       Connection conn;
       PreparedStatement stmt;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/18f7a694/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
index 3a3d1f2..2352e94 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java
@@ -30,7 +30,6 @@ import java.io.EOFException;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -82,8 +81,8 @@ import org.apache.phoenix.schema.TableRef;
 import org.apache.phoenix.schema.stats.GuidePostsInfo;
 import org.apache.phoenix.schema.stats.PTableStats;
 import org.apache.phoenix.util.ByteUtil;
-import org.apache.phoenix.util.PrefixByteCodec;
 import org.apache.phoenix.util.LogUtil;
+import org.apache.phoenix.util.PrefixByteCodec;
 import org.apache.phoenix.util.PrefixByteDecoder;
 import org.apache.phoenix.util.SQLCloseables;
 import org.apache.phoenix.util.ScanUtil;
@@ -382,24 +381,17 @@ public abstract class BaseResultIterators extends 
ExplainTable implements Result
             // For sure we can get the defaultCF from the table
             gps = getDefaultFamilyGuidePosts(guidePostMap, defaultCF);
         } else {
-            byte[] familyInWhere = null;
-            if (!whereConditions.isEmpty()) {
-                if (whereConditions.contains(defaultCF)) {
-                    gps = getDefaultFamilyGuidePosts(guidePostMap, defaultCF);
+            if (whereConditions.isEmpty() || 
whereConditions.contains(defaultCF)) {
+                gps = getDefaultFamilyGuidePosts(guidePostMap, defaultCF);
+            } else {
+                byte[] familyInWhere = whereConditions.iterator().next();
+                GuidePostsInfo guidePostsInfo = 
guidePostMap.get(familyInWhere);
+                if (guidePostsInfo != null) {
+                    gps = guidePostsInfo;
                 } else {
-                    familyInWhere = whereConditions.iterator().next();
-                    if (familyInWhere != null) {
-                        GuidePostsInfo guidePostsInfo = 
guidePostMap.get(familyInWhere);
-                        if (guidePostsInfo != null) {
-                            gps = guidePostsInfo;
-                        } else {
-                            // As there are no guideposts collected for the 
where family we go with the default CF
-                            gps = getDefaultFamilyGuidePosts(guidePostMap, 
defaultCF);
-                        }
-                    }
+                    // As there are no guideposts collected for the where 
family we go with the default CF
+                    gps = getDefaultFamilyGuidePosts(guidePostMap, defaultCF);
                 }
-            } else {
-                gps = getDefaultFamilyGuidePosts(guidePostMap, defaultCF);
             }
         }
         if (gps == null) { return GuidePostsInfo.EMPTY_GUIDEPOST; }
@@ -460,9 +452,12 @@ public abstract class BaseResultIterators extends 
ExplainTable implements Result
         PTable table = getTable();
         boolean isSalted = table.getBucketNum() != null;
         boolean isLocalIndex = table.getIndexType() == IndexType.LOCAL;
-        HashSet<byte[]> whereConditions = new 
HashSet<byte[]>(context.getWhereConditionColumns().size());
+        TreeSet<byte[]> whereConditions = new 
TreeSet<byte[]>(Bytes.BYTES_COMPARATOR);
         for(Pair<byte[], byte[]> where : context.getWhereConditionColumns()) {
-          whereConditions.add(where.getFirst());
+            byte[] cf = where.getFirst();
+            if (cf != null) {
+                whereConditions.add(cf);
+            }
         }
         GuidePostsInfo gps = getGuidePosts(whereConditions);
         boolean traverseAllRegions = isSalted || isLocalIndex;

Reply via email to