You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by th...@apache.org on 2015/09/23 15:21:14 UTC

svn commit: r1704844 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/counter/jmx/ oak-core/src/main/java/org/apache/jackrabbit/oak/query/ oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ oak-core/sr...

Author: thomasm
Date: Wed Sep 23 13:21:13 2015
New Revision: 1704844

URL: http://svn.apache.org/viewvc?rev=1704844&view=rev
Log:
OAK-2852 Query engine: if counter index is not available, cost of traversing is too low

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/counter/jmx/NodeCounter.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/counter/jmx/NodeCounter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/counter/jmx/NodeCounter.java?rev=1704844&r1=1704843&r2=1704844&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/counter/jmx/NodeCounter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/counter/jmx/NodeCounter.java Wed Sep 23 13:21:13 2015
@@ -102,12 +102,12 @@ public class NodeCounter implements Node
         // check in the counter index (if it exists)
         s = child(root,
                 IndexConstants.INDEX_DEFINITIONS_NAME,
-                "counter",
-                NodeCounterEditor.DATA_NODE_NAME);
-        if (s == null) {
+                "counter");
+        if (s == null || !s.exists()) {
             // no index
             return -1;
         }
+        s = child(s, NodeCounterEditor.DATA_NODE_NAME);
         s = child(s, PathUtils.elements(path));
         if (s == null || !s.exists()) {
             // we have an index, but no data

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java?rev=1704844&r1=1704843&r2=1704844&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java Wed Sep 23 13:21:13 2015
@@ -100,6 +100,13 @@ public interface Query {
     String getPlan();
 
     /**
+     * Get the index cost. The query must already be prepared.
+     * 
+     * @return the index cost
+     */
+    String getIndexCost();
+
+    /**
      * Get the estimated cost.
      * 
      * @return the estimated cost

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java?rev=1704844&r1=1704843&r2=1704844&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java Wed Sep 23 13:21:13 2015
@@ -466,6 +466,9 @@ public class QueryImpl implements Query
         prepare();
         if (explain) {
             String plan = getPlan();
+            if (measure) {
+                plan += " cost: { " + getIndexCost() + " }";
+            }
             columns = new ColumnImpl[] { new ColumnImpl("explain", "plan", "plan")};
             ResultRowImpl r = new ResultRowImpl(this,
                     Tree.EMPTY_ARRAY,
@@ -573,6 +576,11 @@ public class QueryImpl implements Query
     }
     
     @Override
+    public String getIndexCost() {
+        return source.getIndexCost(context.getBaseState());
+    }
+
+    @Override
     public double getEstimatedCost() {
         return estimatedCost;
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java?rev=1704844&r1=1704843&r2=1704844&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java Wed Sep 23 13:21:13 2015
@@ -140,7 +140,8 @@ public class SQL2Parser {
         boolean explain = false, measure = false;
         if (readIf("EXPLAIN")) {
             explain = true;
-        } else if (readIf("MEASURE")) {
+        }
+        if (readIf("MEASURE")) {
             measure = true;
         }
         Query q = parseSelect();

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java?rev=1704844&r1=1704843&r2=1704844&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java Wed Sep 23 13:21:13 2015
@@ -236,6 +236,17 @@ public class UnionQueryImpl implements Q
     }
     
     @Override
+    public String getIndexCost() {
+        StringBuilder buff = new StringBuilder();
+        buff.append("{ ");
+        buff.append(left.getIndexCost());
+        buff.append(", ");
+        buff.append(right.getIndexCost());
+        buff.append(" }");
+        return buff.toString();
+    }
+
+    @Override
     public Tree getTree(String path) {
         return left.getTree(path);
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java?rev=1704844&r1=1704843&r2=1704844&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java Wed Sep 23 13:21:13 2015
@@ -46,6 +46,10 @@ abstract class AstElement {
         return '[' + pathOrName + ']';
     }
 
+    protected String quoteJson(String string) {
+        return '"' + string.replaceAll("\"", "\"\"") + '"';
+    }
+
     public void setQuery(QueryImpl query) {
         this.query = query;
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java?rev=1704844&r1=1704843&r2=1704844&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java Wed Sep 23 13:21:13 2015
@@ -110,6 +110,18 @@ public class JoinImpl extends SourceImpl
     }
 
     @Override
+    public String getIndexCost(NodeState rootState) {
+        StringBuilder buff = new StringBuilder();
+        buff.append(toString());
+        buff.append("{ ");
+        buff.append(left.getIndexCost(rootState));
+        buff.append(", ");
+        buff.append(right.getIndexCost(rootState));
+        buff.append(" }");
+        return buff.toString();
+    }
+
+    @Override
     public String toString() {
         return left + " " + joinType +
                 " " + right + " on " + joinCondition;

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java?rev=1704844&r1=1704843&r2=1704844&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java Wed Sep 23 13:21:13 2015
@@ -352,6 +352,25 @@ public class SelectorImpl extends Source
         return buff.toString();
     }
 
+    @Override
+    public String getIndexCost(NodeState rootState) {
+        StringBuilder buff = new StringBuilder();
+        buff.append(quoteJson(selectorName)).append(": ");
+        QueryIndex index = getIndex();
+        if (index != null) {
+            if (index instanceof AdvancedQueryIndex) {
+                IndexPlan p = plan.getIndexPlan();
+                buff.append("{ perEntry: ").append(p.getCostPerEntry());
+                buff.append(", perExecution: ").append(p.getCostPerExecution());
+                buff.append(", count: ").append(p.getEstimatedEntryCount());
+                buff.append(" }");
+            } else {
+                buff.append(index.getCost(createFilter(true), rootState));
+            }
+        }
+        return buff.toString();
+    }
+
     /**
      * Create the filter condition for planning or execution.
      * 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java?rev=1704844&r1=1704843&r2=1704844&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java Wed Sep 23 13:21:13 2015
@@ -86,6 +86,14 @@ public abstract class SourceImpl extends
     public abstract String getPlan(NodeState rootState);
 
     /**
+     * Get the index cost as a JSON string.
+     *
+     * @param rootState the root
+     * @return the cost
+     */
+    public abstract String getIndexCost(NodeState rootState);
+
+    /**
      * Prepare executing the query (recursively). This will 'wire' the
      * selectors with the join constraints, and decide which index to use.
      * 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java?rev=1704844&r1=1704843&r2=1704844&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java Wed Sep 23 13:21:13 2015
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("2.2")
+@Version("2.3")
 @Export(optional = "provide:=true")
 package org.apache.jackrabbit.oak.query;
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java?rev=1704844&r1=1704843&r2=1704844&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java Wed Sep 23 13:21:13 2015
@@ -118,7 +118,8 @@ public class Statement {
         // explain | measure ...
         if (explain) {
             buff.append("explain ");
-        } else if (measure) {
+        } 
+        if (measure) {
             buff.append("measure ");
         }
         
@@ -250,9 +251,10 @@ public class Statement {
         public String toString() {
             StringBuilder buff = new StringBuilder();
             // explain | measure ...
-            if (this.explain) {
+            if (explain) {
                 buff.append("explain ");
-            } else if (measure) {
+            } 
+            if (measure) {
                 buff.append("measure ");
             }
             buff.append(s1).append(" union ").append(s2);

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java?rev=1704844&r1=1704843&r2=1704844&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java Wed Sep 23 13:21:13 2015
@@ -54,6 +54,9 @@ import org.apache.jackrabbit.api.securit
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.commons.JcrUtils;
 import org.apache.jackrabbit.commons.cnd.CndImporter;
+import org.apache.jackrabbit.oak.commons.json.JsonObject;
+import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
+import org.apache.jackrabbit.oak.commons.json.JsopTokenizer;
 import org.apache.jackrabbit.oak.jcr.AbstractRepositoryTest;
 import org.apache.jackrabbit.oak.jcr.NodeStoreFixture;
 import org.junit.Ignore;
@@ -801,5 +804,38 @@ public class QueryTest extends AbstractR
         assertFalse(ni.hasNext());
         session.logout();
     }
+    
+    @Test
+    public void approxCount() throws Exception {
+        Session session = createAdminSession();
+        double c = getCost(session, "//*[@x=1]");
+        // *with* the counter index, the estimated cost to traverse is low
+        assertTrue("cost: " + c, c > 0 && c < 100000);
+        
+        // *without* the counter index, the estimated cost to traverse is high
+        session.getNode("/oak:index/counter").remove();
+        session.save();
+        double c2 = getCost(session, "//*[@x=1]");
+        assertTrue("cost: " + c2, c2 > 1000000);
+
+        session.logout();
+    }
+    
+    private static double getCost(Session session, String xpath) throws RepositoryException {
+        QueryManager qm = session.getWorkspace().getQueryManager();
+        QueryResult qr = qm.createQuery("explain measure " + xpath, "xpath").execute();
+        Row r = qr.getRows().nextRow();
+        String plan = r.getValue("plan").getString();
+        String cost = plan.substring(plan.lastIndexOf('{'));
+        JsonObject json = parseJson(cost);
+        double c = Double.parseDouble(json.getProperties().get("a"));
+        return c;
+    }
+    
+    private static JsonObject parseJson(String json) {
+        JsopTokenizer t = new JsopTokenizer(json);
+        t.read('{');
+        return JsonObject.create(t);
+    }
 
 }



Re: svn commit: r1704844 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/counter/jmx/ oak-core/src/main/java/org/apache/jackrabbit/oak/query/ oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ oak-cor...

Posted by Chetan Mehrotra <ch...@gmail.com>.
On Thu, Sep 24, 2015 at 1:56 PM, Thomas Mueller <mu...@adobe.com> wrote:
> what about getIndexCostInfo

+1

Chetan Mehrotra

Re: svn commit: r1704844 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/counter/jmx/ oak-core/src/main/java/org/apache/jackrabbit/oak/query/ oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ oak-cor...

Posted by Thomas Mueller <mu...@adobe.com>.
Hi,

Yes, makes sense... what about getIndexCostInfo?

Regards,
Thomas


On 24/09/15 07:41, "Chetan Mehrotra" <ch...@gmail.com> wrote:

>Hi Thomas,
>
>On Wed, Sep 23, 2015 at 6:51 PM,  <th...@apache.org> wrote:
>>      /**
>> +     * Get the index cost. The query must already be prepared.
>> +     *
>> +     * @return the index cost
>> +     */
>> +    String getIndexCost();
>
>Should this be returning string? May be we should name it better
>
>Chetan Mehrotra


Re: svn commit: r1704844 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/counter/jmx/ oak-core/src/main/java/org/apache/jackrabbit/oak/query/ oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ oak-core/sr...

Posted by Chetan Mehrotra <ch...@gmail.com>.
Hi Thomas,

On Wed, Sep 23, 2015 at 6:51 PM,  <th...@apache.org> wrote:
>      /**
> +     * Get the index cost. The query must already be prepared.
> +     *
> +     * @return the index cost
> +     */
> +    String getIndexCost();

Should this be returning string? May be we should name it better

Chetan Mehrotra