Author: mreutegg
Date: Tue Feb  2 14:16:03 2016
New Revision: 1728123

URL: http://svn.apache.org/viewvc?rev=1728123&view=rev
Log:
OAK-3071: Add a compound index for _modified + _id

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStoreTest.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java?rev=1728123&r1=1728122&r2=1728123&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
 Tue Feb  2 14:16:03 2016
@@ -102,6 +102,8 @@ import static com.google.common.collect.
 import static com.google.common.collect.Maps.filterKeys;
 import static com.google.common.collect.Maps.filterValues;
 import static com.google.common.collect.Sets.difference;
+import static 
org.apache.jackrabbit.oak.plugins.document.mongo.MongoUtils.createIndex;
+import static 
org.apache.jackrabbit.oak.plugins.document.mongo.MongoUtils.hasIndex;
 
 /**
  * A document store that uses MongoDB as the backend.
@@ -192,6 +194,8 @@ public class MongoDocumentStore implemen
 
     private DocumentStoreStatsCollector stats;
 
+    private boolean hasModifiedIdCompoundIndex = true;
+
     public MongoDocumentStore(DB db, DocumentMK.Builder builder) {
         String version = checkVersion(db);
         metadata = ImmutableMap.<String,String>builder()
@@ -210,40 +214,31 @@ public class MongoDocumentStore implemen
 
         // indexes:
         // the _id field is the primary key, so we don't need to define it
-        DBObject index = new BasicDBObject();
-        // modification time (descending)
-        index.put(NodeDocument.MODIFIED_IN_SECS, -1L);
-        DBObject options = new BasicDBObject();
-        options.put("unique", Boolean.FALSE);
-        nodes.createIndex(index, options);
+
+        // compound index on _modified and _id
+        if (nodes.count() == 0) {
+            // this is an empty store, create a compound index
+            // on _modified and _id (OAK-3071)
+            createIndex(nodes, new String[]{NodeDocument.MODIFIED_IN_SECS, 
Document.ID},
+                    new boolean[]{true, true}, false, false);
+        } else if (!hasIndex(nodes, NodeDocument.MODIFIED_IN_SECS, 
Document.ID)) {
+            hasModifiedIdCompoundIndex = false;
+            LOG.warn("Detected an upgrade from Oak version <= 1.2. For optimal 
" +
+                    "performance it is recommended to create a compound index 
" +
+                    "for the 'nodes' collection on {_modified:1, _id:1}.");
+        }
 
         // index on the _bin flag to faster access nodes with binaries for GC
-        index = new BasicDBObject();
-        index.put(NodeDocument.HAS_BINARY_FLAG, 1);
-        options = new BasicDBObject();
-        options.put("unique", Boolean.FALSE);
-        options.put("sparse", Boolean.TRUE);
-        this.nodes.createIndex(index, options);
-
-        index = new BasicDBObject();
-        index.put(NodeDocument.DELETED_ONCE, 1);
-        options = new BasicDBObject();
-        options.put("unique", Boolean.FALSE);
-        options.put("sparse", Boolean.TRUE);
-        this.nodes.createIndex(index, options);
-
-        index = new BasicDBObject();
-        index.put(NodeDocument.SD_TYPE, 1);
-        options = new BasicDBObject();
-        options.put("unique", Boolean.FALSE);
-        options.put("sparse", Boolean.TRUE);
-        this.nodes.createIndex(index, options);
-
-        index = new BasicDBObject();
-        index.put(JournalEntry.MODIFIED, 1);
-        options = new BasicDBObject();
-        options.put("unique", Boolean.FALSE);
-        this.journal.createIndex(index, options);
+        createIndex(nodes, NodeDocument.HAS_BINARY_FLAG, true, false, true);
+
+        // index on _deleted for fast lookup of potentially garbage
+        createIndex(nodes, NodeDocument.DELETED_ONCE, true, false, true);
+
+        // index on _sdType for fast lookup of split documents
+        createIndex(nodes, NodeDocument.SD_TYPE, true, false, true);
+
+        // index on _modified for journal entries
+        createIndex(journal, JournalEntry.MODIFIED, true, false, false);
 
         this.nodeLocks = new TreeNodeDocumentLocks();
         this.nodesCache = builder.buildNodeDocumentCache(this, nodeLocks);
@@ -595,7 +590,7 @@ public class MongoDocumentStore implemen
         try {
             lockTime = withLock ? watch.elapsed(TimeUnit.MILLISECONDS) : -1;
             DBCursor cursor = dbCollection.find(query).sort(BY_ID_ASC);
-            if (!disableIndexHint) {
+            if (!disableIndexHint && !hasModifiedIdCompoundIndex) {
                 cursor.hint(hint);
             }
             if (maxQueryTime > 0) {

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStoreTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStoreTest.java?rev=1728123&r1=1728122&r2=1728123&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStoreTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStoreTest.java
 Tue Feb  2 14:16:03 2016
@@ -27,12 +27,15 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.document.Collection;
 import org.apache.jackrabbit.oak.plugins.document.Document;
 import org.apache.jackrabbit.oak.plugins.document.DocumentMK;
+import org.apache.jackrabbit.oak.plugins.document.JournalEntry;
 import org.apache.jackrabbit.oak.plugins.document.MongoUtils;
 import org.apache.jackrabbit.oak.plugins.document.NodeDocument;
 import org.apache.jackrabbit.oak.plugins.document.util.Utils;
 import org.junit.Test;
 
+import static 
org.apache.jackrabbit.oak.plugins.document.mongo.MongoUtils.hasIndex;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -79,6 +82,17 @@ public class MongoDocumentStoreTest exte
         fail("No query timeout triggered even after adding " + index + " 
nodes");
     }
 
+    @Test
+    public void defaultIndexes() {
+        assertTrue(hasIndex(store.getDBCollection(Collection.NODES), 
Document.ID));
+        assertTrue(hasIndex(store.getDBCollection(Collection.NODES), 
NodeDocument.SD_TYPE));
+        assertTrue(hasIndex(store.getDBCollection(Collection.NODES), 
NodeDocument.DELETED_ONCE));
+        assertTrue(hasIndex(store.getDBCollection(Collection.NODES), 
NodeDocument.HAS_BINARY_FLAG));
+        assertTrue(hasIndex(store.getDBCollection(Collection.NODES), 
NodeDocument.MODIFIED_IN_SECS, Document.ID));
+        assertFalse(hasIndex(store.getDBCollection(Collection.NODES), 
NodeDocument.MODIFIED_IN_SECS));
+        assertTrue(hasIndex(store.getDBCollection(Collection.JOURNAL), 
JournalEntry.MODIFIED));
+    }
+
     static final class TestStore extends MongoDocumentStore {
 
         AtomicInteger queriesWithoutLock = new AtomicInteger();


Reply via email to