diff --git oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexStats.java oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexStats.java
new file mode 100644
index 0000000..dae498b
--- /dev/null
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexStats.java
@@ -0,0 +1,216 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.plugins.index.property.jmx;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+import com.google.common.collect.TreeTraverser;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.commons.jmx.AnnotatedStandardMBean;
+import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
+import org.apache.jackrabbit.oak.plugins.tree.TreeFactory;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
+import org.osgi.framework.BundleContext;
+
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_CONTENT_NODE_NAME;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.UNIQUE_PROPERTY_NAME;
+import static org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean;
+
+@Component
+public class PropertyIndexStats extends AnnotatedStandardMBean implements PropertyIndexStatsMBean {
+
+    @Reference
+    private NodeStore store;
+
+    private Registration reg;
+
+    public PropertyIndexStats() {
+        super(PropertyIndexStatsMBean.class);
+    }
+
+    @Activate
+    private void activate(BundleContext context){
+        reg = registerMBean(new OsgiWhiteboard(context),
+                PropertyIndexStatsMBean.class,
+                this,
+                PropertyIndexStatsMBean.TYPE,
+                "Property Index statistics");
+    }
+
+    @Deactivate
+    private void deactivate(){
+        if (reg != null){
+            reg.unregister();
+        }
+    }
+
+
+    @Override
+    public CompositeData getStats(String path, int maxValueCount, int maxDepth, int maxPathCount) throws
+            OpenDataException {
+        NodeState idx = NodeStateUtils.getNode(store.getRoot(), path);
+
+        Map<String, Object> result = new HashMap<String, Object>();
+
+        //Add placeholder
+        result.put("values", new String[0]);
+        result.put("paths", new String[0]);
+        result.put("valueCount", -1L);
+        result.put("pathCount", -1);
+        result.put("maxPathCount", maxPathCount);
+        result.put("maxDepth", maxDepth);
+        result.put("maxValueCount", maxValueCount);
+
+        String status = "No index found at path " + path;
+        NodeState data = idx.getChildNode(INDEX_CONTENT_NODE_NAME);
+        if (data.exists()) {
+            if (idx.getBoolean(UNIQUE_PROPERTY_NAME)){
+                status = "stats not supported for unique indexes";
+            } else {
+                long childNodeCount = data.getChildNodeCount(maxValueCount);
+                if (childNodeCount == Long.MAX_VALUE || childNodeCount > maxValueCount){
+                    status = String.format("stats cannot be determined as number of values exceed the max limit of " +
+                            "[%d]. Estimated value count [%d]", maxValueCount, childNodeCount);
+                } else {
+                    String[] values = Iterables.toArray(
+                            Iterables.limit(data.getChildNodeNames(), maxValueCount),
+                            String.class
+                    );
+
+                    String[] paths = determineIndexedPaths(
+                            Iterables.limit(data.getChildNodeEntries(), maxValueCount), maxDepth, maxPathCount);
+                    result.put("values", values);
+                    result.put("paths", paths);
+                    result.put("pathCount", paths.length);
+                    status = "Result determined and above path list can be safely used based on current indexed data";
+                }
+                result.put("valueCount", childNodeCount);
+            }
+        }
+
+        result.put("status", status);
+        return new CompositeDataSupport(getType(), result);
+    }
+
+    private String[] determineIndexedPaths(Iterable<? extends ChildNodeEntry> values,
+                                           final int maxDepth, int maxPathCount) {
+        Set<String> paths = Sets.newHashSet();
+        Set<String> intermediatePaths = Sets.newHashSet();
+        int maxPathLimitBreachedAtLevel = -1;
+        topLevel:
+        for (ChildNodeEntry cne : values){
+            Tree t = TreeFactory.createReadOnlyTree(cne.getNodeState());
+            TreeTraverser<Tree> traverser = new TreeTraverser<Tree>() {
+                @Override
+                public Iterable<Tree> children(Tree root) {
+                    //Break at maxLevel
+                    if (PathUtils.getDepth(root.getPath()) >= maxDepth){
+                        return Collections.emptyList();
+                    }
+                    return root.getChildren();
+                }
+            };
+            for (Tree node : traverser.breadthFirstTraversal(t)){
+                PropertyState matchState = node.getProperty("match");
+                boolean match = matchState == null ? false : matchState.getValue(Type.BOOLEAN);
+                int depth = PathUtils.getDepth(node.getPath());
+
+                //Intermediate nodes which are not leaf are not to be included
+                if (depth < maxDepth && !match){
+                    intermediatePaths.add(node.getPath());
+                    continue;
+                }
+
+                if (paths.size() < maxPathCount){
+                    paths.add(node.getPath());
+                } else {
+                    maxPathLimitBreachedAtLevel = depth;
+                    break topLevel;
+                }
+            }
+        }
+
+        if (maxPathLimitBreachedAtLevel < 0){
+            return Iterables.toArray(paths, String.class);
+        }
+
+        //If max limit for path is reached then we can safely
+        //say about includedPaths upto depth = level at which limit reached - 1
+        //As for that level we know *all* the path roots
+        Set<String> result = Sets.newHashSet();
+        int safeDepth = maxPathLimitBreachedAtLevel - 1;
+        if (safeDepth > 0){
+            for (String path : intermediatePaths){
+                int pathDepth = PathUtils.getDepth(path);
+                if (pathDepth == safeDepth){
+                    result.add(path);
+                }
+            }
+        }
+        return Iterables.toArray(result, String.class);
+    }
+
+
+
+    private static CompositeType getType() {
+        try {
+            return new CompositeType("PropertyIndexStats", "Property index related stats",
+                    new String[]{"values", "paths", "valueCount", "status", "pathCount", "maxPathCount", "maxDepth", "maxValueCount"},
+                    new String[]{"values", "paths", "valueCount", "status", "pathCount", "maxPathCount", "maxDepth", "maxValueCount"},
+                    new OpenType[]{
+                            new ArrayType(SimpleType.STRING, false),
+                            new ArrayType(SimpleType.STRING, false),
+                            SimpleType.LONG,
+                            SimpleType.STRING,
+                            SimpleType.INTEGER,
+                            SimpleType.INTEGER,
+                            SimpleType.INTEGER,
+                            SimpleType.INTEGER,
+                    });
+        } catch (OpenDataException e) {
+
+        }
+        return null;
+    }
+}
diff --git oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexStatsMBean.java oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexStatsMBean.java
new file mode 100644
index 0000000..987762b
--- /dev/null
+++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexStatsMBean.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.plugins.index.property.jmx;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.OpenDataException;
+
+import org.apache.jackrabbit.oak.commons.jmx.Description;
+import org.apache.jackrabbit.oak.commons.jmx.Name;
+
+public interface PropertyIndexStatsMBean {
+    String TYPE = "PropertyIndexStatsMBean";
+
+    @Description("Determines statistics related to property index which can be used to optimize property index " +
+            "definition. Various limits below are provided to ensure that estimation logic does not consume too much " +
+            "resources. If any limits are reached then report would not be considered conclusive and would not have " +
+            "paths set determined")
+    CompositeData getStats(@Name("path")
+                           @Description("Index path for which stats are to be determined")
+                           String path,
+                           @Name("maxValueCount")
+                           @Description("Maximum number of values to examine. E.g. 100. Stats calculation would " +
+                                   "break out after this limit")
+                           int maxValueCount,
+                           @Description("Maximum depth to examine. E.g. 5. Stats calculation would " +
+                                   "break out after this limit")
+                           @Name("maxDepth")
+                           int maxDepth,
+                           @Description("Maximum number of unique paths to examine. E.g. 100. Stats " +
+                                   "calculation would break out after this limit")
+                           @Name("maxPathCount")
+                           int maxPathCount
+    ) throws OpenDataException;
+
+
+}
