Uploaded image for project: 'ModeShape'
  1. ModeShape
  2. MODE-2312

Implicit index for node identifier not used when querying for [jcr:uuid]

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • Blocker
    • 4.0.0.Final
    • 4.0.0.Beta2
    • Query
    • None

    Description

      When firing this query

      SELECT A.* FROM [nt:someTypeWithMixReferencable] AS A
      WHERE A.[jcr:uuid] = $uuid
      

      There thould be an implicit index being used but it is not:

      Access [A]
        Project [A] <PROJECT_COLUMNS=[A.[jcr:primaryType], A.[jcr:mixinTypes], A.[jcr:score], A.[mode:depth], A.[jcr:path], A.[jcr:name], A.[mode:localName], A.[mode:id]], PROJECT_COLUMN_TYPES=[STRING, STRING, DOUBLE, LONG, STRING, STRING, STRING, STRING]>
          Select [A] <SELECT_CRITERIA=A.[jcr:uuid] = $uuid>
            Select [A] <SELECT_CRITERIA=A.[jcr:primaryType] = 'nt:someTypeWithMixReferencable'>
              Source [A] <SOURCE_NAME=__ALLNODES__, SOURCE_ALIAS=A, SOURCE_COLUMNS=[jcr:frozenUuid(STRING), mode:sharedUuid(STRING), mode:nodeTypeName(STRING), jcr:defaultValues(STRING), mode:projectedNodeKey(STRING), jcr:mixinTypes(STRING), jcr:frozenPrimaryType(STRING), jcr:defaultPrimaryType(STRING), jcr:statement(STRING), jcr:lastModifiedBy(STRING), jcr:mimeType(STRING), jcr:hasOrderableChildNodes(BOOLEAN), jcr:etag(STRING), jcr:encoding(STRING), jcr:root(STRING), mode:kind(STRING), jcr:supertypes(STRING), jcr:successors(STRING), jcr:primaryItemName(STRING), jcr:hold(STRING), jcr:workspace(STRING), jcr:isDeep(BOOLEAN), jcr:primaryType(STRING), mode:externalNodeKey(STRING), mode:derivedFrom(STRING), mode:isHeldBySession(BOOLEAN), jcr:baseVersion(STRING), jcr:lastModified(DATE), jcr:mergeFailed(STRING), mode:derivedAt(DATE), jcr:requiredPrimaryTypes(STRING), jcr:multiple(BOOLEAN), mode:generated(BOOLEAN), jcr:activityTitle(STRING), jcr:lifecyclePolicy(STRING), jcr:isMixin(BOOLEAN), jcr:availableQueryOperators(STRING), jcr:childVersionHistory(STRING), jcr:content(STRING), jcr:autoCreated(BOOLEAN), mode:synchronous(BOOLEAN), name(STRING), mode:alias(STRING), jcr:createdBy(STRING), jcr:isFullTextSearchable(BOOLEAN), jcr:uuid(STRING), jcr:onParentVersion(STRING), mode:expirationDate(DATE), jcr:copiedFrom(STRING), mode:lockToken(STRING), jcr:title(STRING), jcr:isAbstract(BOOLEAN), jcr:versionableUuid(STRING), jcr:versionHistory(STRING), jcr:predecessors(STRING), jcr:lockIsDeep(BOOLEAN), jcr:lockOwner(STRING), mode:sha1(STRING), jcr:repository(STRING), mode:columnTypeName(STRING), jcr:created(DATE), jcr:frozenMixinTypes(STRING), jcr:description(STRING), jcr:text(STRING), jcr:host(STRING), jcr:configuration(STRING), jcr:port(STRING), mode:workspace(STRING), jcr:nodeTypeName(STRING), jcr:isQueryable(BOOLEAN), jcr:data(BINARY), jcr:language(STRING), jcr:isQueryOrderable(BOOLEAN), jcr:isCheckedOut(BOOLEAN), jcr:mandatory(BOOLEAN), jcr:protected(BOOLEAN), jcr:protocol(STRING), jcr:sameNameSiblings(BOOLEAN), jcr:requiredType(STRING), mode:lockingSession(STRING), jcr:messageId(STRING), jcr:id(STRING), mode:uri(STRING), mode:propertyName(STRING), mode:workspaces(STRING), privileges(STRING), mode:isSessionScoped(BOOLEAN), jcr:valueConstraints(STRING), jcr:retentionPolicy(STRING), jcr:activity(STRING), jcr:currentLifecycleState(STRING), jcr:score(DOUBLE), mode:depth(LONG), jcr:path(STRING), jcr:name(STRING), mode:localName(STRING), mode:id(STRING)]>
      

      The query takes about 200 ms on a relatively empty repository. If I define an index on [jcr:uuid] myself, it takes under 20ms and I get this plan as a result:

      Access [A]
        Project [A] <PROJECT_COLUMNS=[A.[jcr:primaryType], A.[jcr:mixinTypes], A.[jcr:score], A.[mode:depth], A.[jcr:path], A.[jcr:name], A.[mode:localName], A.[mode:id]], PROJECT_COLUMN_TYPES=[STRING, STRING, DOUBLE, LONG, STRING, STRING, STRING, STRING]>
          Select [A] <SELECT_CRITERIA=A.[jcr:uuid] = $uuid>
            Select [A] <SELECT_CRITERIA=A.[jcr:primaryType] = 'nt:someTypeWithMixReferencable'>
              Source [A] <SOURCE_NAME=__ALLNODES__, SOURCE_ALIAS=A, SOURCE_COLUMNS=[jcr:frozenUuid(STRING), mode:sharedUuid(STRING), mode:nodeTypeName(STRING), jcr:defaultValues(STRING), mode:projectedNodeKey(STRING), jcr:mixinTypes(STRING), jcr:frozenPrimaryType(STRING), jcr:defaultPrimaryType(STRING), jcr:statement(STRING), jcr:lastModifiedBy(STRING), jcr:mimeType(STRING), jcr:hasOrderableChildNodes(BOOLEAN), jcr:etag(STRING), jcr:encoding(STRING), jcr:root(STRING), mode:kind(STRING), jcr:supertypes(STRING), jcr:successors(STRING), jcr:primaryItemName(STRING), jcr:hold(STRING), jcr:workspace(STRING), jcr:isDeep(BOOLEAN), jcr:primaryType(STRING), mode:externalNodeKey(STRING), mode:derivedFrom(STRING), mode:isHeldBySession(BOOLEAN), jcr:baseVersion(STRING), jcr:lastModified(DATE), jcr:mergeFailed(STRING), mode:derivedAt(DATE), jcr:requiredPrimaryTypes(STRING), jcr:multiple(BOOLEAN), mode:generated(BOOLEAN), jcr:activityTitle(STRING), jcr:lifecyclePolicy(STRING), jcr:isMixin(BOOLEAN), jcr:availableQueryOperators(STRING), jcr:childVersionHistory(STRING), jcr:content(STRING), jcr:autoCreated(BOOLEAN), mode:synchronous(BOOLEAN), name(STRING), mode:alias(STRING), jcr:createdBy(STRING), jcr:isFullTextSearchable(BOOLEAN), jcr:uuid(STRING), jcr:onParentVersion(STRING), mode:expirationDate(DATE), jcr:copiedFrom(STRING), mode:lockToken(STRING), jcr:title(STRING), jcr:isAbstract(BOOLEAN), jcr:versionableUuid(STRING), jcr:versionHistory(STRING), jcr:predecessors(STRING), jcr:lockIsDeep(BOOLEAN), jcr:lockOwner(STRING), mode:sha1(STRING), jcr:repository(STRING), mode:columnTypeName(STRING), jcr:created(DATE), jcr:frozenMixinTypes(STRING), jcr:description(STRING), jcr:text(STRING), jcr:host(STRING), jcr:configuration(STRING), jcr:port(STRING), mode:workspace(STRING), jcr:nodeTypeName(STRING), jcr:isQueryable(BOOLEAN), jcr:data(BINARY), jcr:language(STRING), jcr:isQueryOrderable(BOOLEAN), jcr:isCheckedOut(BOOLEAN), jcr:mandatory(BOOLEAN), jcr:protected(BOOLEAN), jcr:protocol(STRING), jcr:sameNameSiblings(BOOLEAN), jcr:requiredType(STRING), mode:lockingSession(STRING), jcr:messageId(STRING), jcr:id(STRING), mode:uri(STRING), mode:propertyName(STRING), mode:workspaces(STRING), privileges(STRING), mode:isSessionScoped(BOOLEAN), jcr:valueConstraints(STRING), jcr:retentionPolicy(STRING), jcr:activity(STRING), jcr:currentLifecycleState(STRING), jcr:score(DOUBLE), mode:depth(LONG), jcr:path(STRING), jcr:name(STRING), mode:localName(STRING), mode:id(STRING)]>
                Index [A] <INDEX_SPECIFICATION=uuid, provider=local, cost~=100, cardinality~=0, selectivity~=0.0, constraints=[A.[jcr:uuid] = $uuid], INDEX_USED=true>
      

      Testcase follows, it assumes there is one index being used without defining anything. Although I have never seen such in implicit index popping up in the plan.

      @RunWith(CdiTestRunner.class)
      @TestControl(startScopes = RequestScoped.class, projectStage = UnitTest.class)
      @FixMethodOrder(MethodSorters.NAME_ASCENDING)
      //@Ignore
      public class WmModeshapeIndexWhenSearchingForUuidTest {
      
      	
      	@Inject
      	private Session session;
      
      	@Inject
      	protected transient LogHelper logger;
      
      	@Test
      	public void test001CheckSomethingWithIndexes() throws RepositoryException, InterruptedException {
      
      		regNodeType(session,"nt:someTypeWithMixReferencable");
      		//ensureIndex(indexManager(), "uuid", IndexDefinition.IndexKind.VALUE, "local", "nt:someTypeWithMixReferencable", "", null, "jcr:uuid", PropertyType.NAME);
      		
      		Node newNode1 = session.getRootNode().addNode("nodeWithSysName","nt:someTypeWithMixReferencable");
      		newNode1.addMixin("mix:referenceable");
      		
      		session.save();
      		
      		Thread.sleep(500);
      
      		
      		Query q = session.getWorkspace().getQueryManager().createQuery(
      		"SELECT A.* FROM [nt:someTypeWithMixReferencable] AS A\n" +
      		"WHERE A.[jcr:uuid] = $uuid",Query.JCR_SQL2);
      		q.bindValue("uuid", session.getValueFactory().createValue(UUID.randomUUID().toString()));
      		
      		logger.info(q.getStatement());
      		
      		QueryResult result = q.execute();
      		
      		String plan = ((org.modeshape.jcr.api.query.QueryResult)result).getPlan();
      		logger.info(plan);
      		
      		Assert.assertEquals(1,countIndexes(plan));
      		
      	}
      	
      	private int countIndexes(String plan){
      		
      		Pattern p = Pattern.compile("INDEX_USED=true");
      		Matcher m = p.matcher(plan);
      		int count = 0;
      		while (m.find()){
      			count +=1;
      		}
      		return count;
      	}
      	
      	protected IndexManager indexManager(){
      		
      		if (!(session instanceof org.modeshape.jcr.api.Session)){
      			return null;
      		}
      		
      		try {
      			return ((org.modeshape.jcr.api.Session) session).getWorkspace().getIndexManager();
      		} catch (RepositoryException ex) {
      			logger.error(ex.toString(), ex);
      		}
      		return null;
      	}
      	
      	protected void ensureIndex(IndexManager manager, String indexName, IndexDefinition.IndexKind kind, String providerName, String indexedNodeType, String desc, String workspaceNamePattern, String propertyName, int propertyType) throws RepositoryException {
      
      
      		if (manager.getIndexDefinitions().containsKey(indexName)){
      			return;
      		}
      		
      		logger.info("registering index on property "+propertyName+", type "+indexedNodeType);
      		
      		// Create the index template ...
      		IndexDefinitionTemplate template = manager.createIndexDefinitionTemplate();
      		template.setName(indexName);
      		template.setKind(kind);
      		template.setNodeTypeName(indexedNodeType);
      		template.setProviderName(providerName);
      		if (workspaceNamePattern != null) {
      			template.setWorkspaceNamePattern(workspaceNamePattern);
      		} else {
      			template.setAllWorkspaces();
      		}
      		if (desc != null) {
      			template.setDescription(desc);
      		}
      		
      		// Set up the columns ...
      		IndexColumnDefinition colDefn = manager.createIndexColumnDefinitionTemplate().setPropertyName(propertyName).setColumnType(propertyType);
      		template.setColumnDefinitions(colDefn);
      
      		// Register the index ...
      		manager.registerIndex(template, true);
      	}
      	
      	private void regNodeType(Session repoSession, String typeName) throws RepositoryException{
      			NodeTypeManager mgr = repoSession.getWorkspace().getNodeTypeManager();
      
      			// Create a template for the node type ...
      			NodeTypeTemplate type = mgr.createNodeTypeTemplate();
      			type.setName(typeName);
      			type.setDeclaredSuperTypeNames(new String[]{CrConstants.JCR_NT_UNSTRUCTURED});
      			type.setAbstract(false);
      			type.setOrderableChildNodes(true);
      			type.setMixin(false);
      			type.setQueryable(true);
      			mgr.registerNodeType(type, true);
      	}
      }
      

      Attachments

        Activity

          People

            rhauch Randall Hauch (Inactive)
            bes82 Bjoern Schmidt (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: