Work on perf

This commit is contained in:
James Agnew 2017-04-14 09:50:05 -04:00
parent 1039bbec97
commit f6acb5633b
5 changed files with 146 additions and 53 deletions

View File

@ -977,15 +977,19 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override
public Set<Long> searchForIdsWithAndOr(SearchParameterMap theParams) {
theParams.setPersistResults(false);
SearchBuilder builder = newSearchBuilder();
builder.setType(getResourceType(), getResourceName());
List<Long> result = builder.loadSearchPage(theParams, 0, 100);
// FIXME: fail if too many results
HashSet<Long> retVal = new HashSet<Long>(result);
HashSet<Long> retVal = new HashSet<Long>();
Iterator<Long> iter = builder.createQuery(theParams);
while (iter.hasNext()) {
retVal.add(iter.next());
}
return retVal;
}

View File

@ -1559,11 +1559,12 @@ public class SearchBuilder {
/*
* Now perform the search
*/
TypedQuery<Long> query = myEntityManager.createQuery(outerQuery);
final Iterator<Long> results = query.getResultList().iterator();
final Set<Long> pidSet = new HashSet<Long>();
final TypedQuery<Long> query = myEntityManager.createQuery(outerQuery);
return new Iterator<Long>() {
private final Set<Long> myPidSet = new HashSet<Long>();
private Iterator<Long> myResultsIterator;
private Long myNext;
@Override
@ -1578,10 +1579,13 @@ public class SearchBuilder {
}
private void fetchNext() {
if (myResultsIterator == null) {
myResultsIterator = query.getResultList().iterator();
}
if (myNext == null) {
while (results.hasNext()) {
Long next = results.next();
if (next != null && pidSet.add(next)) {
while (myResultsIterator.hasNext()) {
Long next = myResultsIterator.next();
if (next != null && myPidSet.add(next)) {
myNext = next;
break;
}
@ -1604,45 +1608,42 @@ public class SearchBuilder {
private static Long NO_MORE = Long.valueOf(-1);
public IBundleProvider search(final SearchParameterMap theParams) {
myParams = theParams;
StopWatch w = new StopWatch();
if (theParams.isLoadSynchronous()) {
}
mySearchEntity = new Search();
mySearchEntity.setUuid(UUID.randomUUID().toString());
mySearchEntity.setCreated(new Date());
mySearchEntity.setTotalCount(-1);
mySearchEntity.setPreferredPageSize(myParams.getCount());
mySearchEntity.setSearchType(myParams.getEverythingMode() != null ? SearchTypeEnum.EVERYTHING : SearchTypeEnum.SEARCH);
mySearchEntity.setLastUpdated(myParams.getLastUpdated());
mySearchEntity.setResourceType(myResourceName);
for (Include next : myParams.getIncludes()) {
mySearchEntity.getIncludes().add(new SearchInclude(mySearchEntity, next.getValue(), false, next.isRecurse()));
}
for (Include next : myParams.getRevIncludes()) {
mySearchEntity.getIncludes().add(new SearchInclude(mySearchEntity, next.getValue(), true, next.isRecurse()));
}
List<Long> firstPage = loadSearchPage(theParams, 0, 999);
mySearchEntity.setTotalCount(firstPage.size());
myEntityManager.persist(mySearchEntity);
for (SearchInclude next : mySearchEntity.getIncludes()) {
myEntityManager.persist(next);
}
IBundleProvider retVal = doReturnProvider();
ourLog.info("Search initial phase completed in {}ms", w);
return retVal;
}
public List<Long> loadSearchPage(SearchParameterMap theParams, int theFromIndex, int theToIndex) {
// myParams = theParams;
// StopWatch w = new StopWatch();
//
// if (theParams.isLoadSynchronous()) {
//
// }
//
// mySearchEntity = new Search();
// mySearchEntity.setUuid(UUID.randomUUID().toString());
// mySearchEntity.setCreated(new Date());
// mySearchEntity.setTotalCount(-1);
// mySearchEntity.setPreferredPageSize(myParams.getCount());
// mySearchEntity.setSearchType(myParams.getEverythingMode() != null ? SearchTypeEnum.EVERYTHING : SearchTypeEnum.SEARCH);
// mySearchEntity.setLastUpdated(myParams.getLastUpdated());
// mySearchEntity.setResourceType(myResourceName);
//
// for (Include next : myParams.getIncludes()) {
// mySearchEntity.getIncludes().add(new SearchInclude(mySearchEntity, next.getValue(), false, next.isRecurse()));
// }
// for (Include next : myParams.getRevIncludes()) {
// mySearchEntity.getIncludes().add(new SearchInclude(mySearchEntity, next.getValue(), true, next.isRecurse()));
// }
//
// List<Long> firstPage = loadSearchPage(theParams, 0, 999);
// mySearchEntity.setTotalCount(firstPage.size());
//
// myEntityManager.persist(mySearchEntity);
// for (SearchInclude next : mySearchEntity.getIncludes()) {
// myEntityManager.persist(next);
// }
//
// IBundleProvider retVal = doReturnProvider();
//
// ourLog.info("Search initial phase completed in {}ms", w);
// return retVal;
return null;
}
// public IBundleProvider loadPage(SearchParameterMap theParams, int theFromIndex, int theToIndex) {

View File

@ -0,0 +1,5 @@
package ca.uhn.fhir.jpa.search;
public class ISearchCoordinatorSvc {
}

View File

@ -125,15 +125,15 @@ public final class PersistedJpaBundleProvider implements IBundleProvider {
// List<Long> pidsSubList = sb.loadSearchPage(parameterMap, theFromIndex, theToIndex);());
List<Long> pidsSubList = null;
Set<Long> revIncludedPids = new HashSet<Long>();
Set<Long> includedPids = new HashSet<Long>();
if (mySearchEntity.getSearchType() == SearchTypeEnum.SEARCH) {
revIncludedPids.addAll(SearchBuilder.loadReverseIncludes(myDao, myContext, myEntityManager, pidsSubList, mySearchEntity.toRevIncludesList(), true, mySearchEntity.getLastUpdated()));
includedPids.addAll(SearchBuilder.loadReverseIncludes(myDao, myContext, myEntityManager, pidsSubList, mySearchEntity.toRevIncludesList(), true, mySearchEntity.getLastUpdated()));
}
revIncludedPids.addAll(SearchBuilder.loadReverseIncludes(myDao, myContext, myEntityManager, pidsSubList, mySearchEntity.toIncludesList(), false, mySearchEntity.getLastUpdated()));
includedPids.addAll(SearchBuilder.loadReverseIncludes(myDao, myContext, myEntityManager, pidsSubList, mySearchEntity.toIncludesList(), false, mySearchEntity.getLastUpdated()));
// Execute the query and make sure we return distinct results
List<IBaseResource> resources = new ArrayList<IBaseResource>();
SearchBuilder.loadResourcesByPid(pidsSubList, resources, revIncludedPids, false, myEntityManager, myContext, myDao);
SearchBuilder.loadResourcesByPid(pidsSubList, resources, includedPids, false, myEntityManager, myContext, myDao);
return resources;
}

View File

@ -0,0 +1,83 @@
package ca.uhn.fhir.jpa.search;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.persistence.EntityManager;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.transaction.PlatformTransactionManager;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.IDao;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.dao.SearchBuilder;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamUriDao;
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
import ca.uhn.fhir.jpa.util.StopWatch;
import ca.uhn.fhir.rest.server.IBundleProvider;
public class SearchCoordinatorSvcImpl {
public SearchCoordinatorSvcImpl() {
CustomizableThreadFactory threadFactory = new CustomizableThreadFactory("search_coord_");
myExecutor = Executors.newCachedThreadPool(threadFactory);
}
public IBundleProvider registerSearch(IDao theCallingDao, SearchParameterMap theParams) {
StopWatch w = new StopWatch();
if (theParams.isLoadSynchronous()) {
SearchBuilder sb = theCallingDao.newSearchBuilder();
Iterator<Long> resultIter = sb.createQuery(theParams);
// Load the results synchronously
List<Long> pids = new ArrayList<Long>();
while (resultIter.hasNext()) {
pids.add(resultIter.next());
if (theParams.getLoadSynchronousUpTo() != null && pids.size() >= theParams.getLoadSynchronousUpTo()) {
break;
}
}
resources = sb.loadResourcesByPid(pids, theResourceListToPopulate, theRevIncludedPids, theForHistoryOperation, entityManager, context, theDao);
}
mySearchEntity = new Search();
mySearchEntity.setUuid(UUID.randomUUID().toString());
mySearchEntity.setCreated(new Date());
mySearchEntity.setTotalCount(-1);
mySearchEntity.setPreferredPageSize(myParams.getCount());
mySearchEntity.setSearchType(myParams.getEverythingMode() != null ? SearchTypeEnum.EVERYTHING : SearchTypeEnum.SEARCH);
mySearchEntity.setLastUpdated(myParams.getLastUpdated());
mySearchEntity.setResourceType(myResourceName);
for (Include next : myParams.getIncludes()) {
mySearchEntity.getIncludes().add(new SearchInclude(mySearchEntity, next.getValue(), false, next.isRecurse()));
}
for (Include next : myParams.getRevIncludes()) {
mySearchEntity.getIncludes().add(new SearchInclude(mySearchEntity, next.getValue(), true, next.isRecurse()));
}
List<Long> firstPage = loadSearchPage(theParams, 0, 999);
mySearchEntity.setTotalCount(firstPage.size());
myEntityManager.persist(mySearchEntity);
for (SearchInclude next : mySearchEntity.getIncludes()) {
myEntityManager.persist(next);
}
IBundleProvider retVal = doReturnProvider();
ourLog.info("Search initial phase completed in {}ms", w);
return retVal;
}
}