>From <[email protected]>:

[email protected] has uploaded this change for review. ( 
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17491 )


Change subject: [ASTERIXDB-3167][COMP] Analytics CBO is choosing suboptimal 
index paths
......................................................................

[ASTERIXDB-3167][COMP] Analytics CBO is choosing suboptimal index paths

Change-Id: I856b923d21e6c4e9bc7e65dd9043bdf17bfe502b
---
M 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
1 file changed, 118 insertions(+), 0 deletions(-)



  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/91/17491/1

diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
index f021845..b825986 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
@@ -26,10 +26,12 @@
 import java.util.TreeMap;

 import org.apache.asterix.algebra.operators.CommitOperator;
+import org.apache.asterix.common.config.DatasetConfig;
 import org.apache.asterix.common.exceptions.CompilationException;
 import org.apache.asterix.common.exceptions.ErrorCode;
 import org.apache.asterix.metadata.declared.MetadataProvider;
 import org.apache.asterix.metadata.entities.Index;
+import org.apache.asterix.metadata.utils.ArrayIndexUtil;
 import 
org.apache.asterix.optimizer.rules.am.array.IIntroduceAccessMethodRuleLocalRewrite;
 import org.apache.asterix.optimizer.rules.am.array.MergedSelectRewrite;
 import org.apache.asterix.optimizer.rules.am.array.SelectFromSubplanRewrite;
@@ -370,6 +372,112 @@
         return lop;
     }

+    // list1 is <= list2 in terms of size; so check if everything in list1 is 
also in list2 in the same order
+    protected boolean prefix(List<List<String>> list1, List<List<String>> 
list2) {
+        int i, j;
+
+        for (i = 0; i < list1.size(); i++) {
+            List<String> l1 = list1.get(i);
+            List<String> l2 = list2.get(i);
+            if (l1.size() != l2.size()) {
+                return false;
+            }
+            for (j = 0; j < l1.size(); j++) {
+                String s1 = l1.get(j);
+                String s2 = l2.get(j);
+                if (!(s1.equals(s2))) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    // This code was lifted from AbstractIntroduceAccessMethodRule and 
modified.
+    // Harder to refactor as the other code was also getting keyTypes
+    protected List<List<String>> findKeyFieldNames(Index index) throws 
CompilationException {
+        List<List<String>> keyFieldNames;
+        DatasetConfig.IndexType indexType = index.getIndexType();
+        switch (Index.IndexCategory.of(indexType)) {
+            case ARRAY:
+                Index.ArrayIndexDetails arrayIndexDetails = 
(Index.ArrayIndexDetails) index.getIndexDetails();
+                keyFieldNames = new ArrayList<>();
+
+                for (Index.ArrayIndexElement e : 
arrayIndexDetails.getElementList()) {
+                    for (int i = 0; i < e.getProjectList().size(); i++) {
+                        List<String> project = e.getProjectList().get(i);
+                        
keyFieldNames.add(ArrayIndexUtil.getFlattenedKeyFieldNames(e.getUnnestList(), 
project));
+                    }
+                }
+                break;
+            case VALUE:
+                Index.ValueIndexDetails valueIndexDetails = 
(Index.ValueIndexDetails) index.getIndexDetails();
+                keyFieldNames = valueIndexDetails.getKeyFieldNames();
+
+                break;
+            case TEXT:
+                Index.TextIndexDetails textIndexDetails = 
(Index.TextIndexDetails) index.getIndexDetails();
+                keyFieldNames = textIndexDetails.getKeyFieldNames();
+
+                break;
+            default:
+                throw new 
CompilationException(ErrorCode.COMPILATION_UNKNOWN_INDEX_TYPE, 
String.valueOf(indexType));
+        }
+
+        return keyFieldNames;
+
+    }
+
+    protected void removeSmallerPrefixIndexes(List<Pair<IAccessMethod, Index>> 
indexes) throws CompilationException {
+        int len = indexes.size();
+        int i, j;
+        Index index_i, index_j;
+        boolean include[];
+        include = new boolean[len];
+        for (i = 0; i < len; i++) {
+            include[i] = true;           // Initially every index is included.
+        }
+
+        List<List<String>> fieldNames_i, fieldNames_j;
+
+        for (i = 0; i < len - 1; i++) {
+            if (include[i]) {
+                IAccessMethod ami = indexes.get(i).first;
+                index_i = indexes.get(i).second;
+                DatasetConfig.IndexType type_i = index_i.getIndexType();
+
+                fieldNames_i = findKeyFieldNames(index_i);
+
+                for (j = i + 1; j < len; j++) {
+                    if (include[j]) {
+                        IAccessMethod amj = indexes.get(j).first;
+                        if (ami == amj) { // should be the same accessMethods
+                            index_j = indexes.get(j).second;
+                            DatasetConfig.IndexType type_j = 
index_j.getIndexType();
+                            if (type_i == type_j) {
+                                fieldNames_j = findKeyFieldNames(index_j);
+                                if (fieldNames_i.size() <= 
fieldNames_j.size()) {
+                                    if (prefix(fieldNames_i, fieldNames_j)) {
+                                        include[i] = false;
+                                    }
+                                } else if (prefix(fieldNames_j, fieldNames_i)) 
{
+                                    include[j] = false;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // remove the shorter indexes if any
+        for (i = len - 1; i >= 0; i--) { // removing from the end; seems safer 
that way
+            if (!include[i]) { // if this index can be removed it, do so;
+                indexes.remove(i);
+            }
+        }
+    }
+
     /**
      * Recursively traverse the given plan and check whether a SELECT operator 
exists.
      * If one is found, maintain the path from the root to SELECT operator and
@@ -484,6 +592,7 @@

                 // Choose all indexes that will be applied.
                 chooseAllIndexes(analyzedAMs, chosenIndexes);
+                removeSmallerPrefixIndexes(chosenIndexes);

                 if (chosenIndexes == null || chosenIndexes.isEmpty()) {
                     // We can't apply any index for this SELECT operator

--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17491
To unsubscribe, or for help writing mail filters, visit 
https://asterix-gerrit.ics.uci.edu/settings

Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Change-Id: I856b923d21e6c4e9bc7e65dd9043bdf17bfe502b
Gerrit-Change-Number: 17491
Gerrit-PatchSet: 1
Gerrit-Owner: [email protected]
Gerrit-MessageType: newchange

Reply via email to