Work on perf
This commit is contained in:
parent
1039bbec97
commit
f6acb5633b
|
@ -977,15 +977,19 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Long> searchForIdsWithAndOr(SearchParameterMap theParams) {
|
public Set<Long> searchForIdsWithAndOr(SearchParameterMap theParams) {
|
||||||
theParams.setPersistResults(false);
|
|
||||||
|
|
||||||
SearchBuilder builder = newSearchBuilder();
|
SearchBuilder builder = newSearchBuilder();
|
||||||
builder.setType(getResourceType(), getResourceName());
|
builder.setType(getResourceType(), getResourceName());
|
||||||
List<Long> result = builder.loadSearchPage(theParams, 0, 100);
|
|
||||||
|
|
||||||
// FIXME: fail if too many results
|
// 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;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1559,11 +1559,12 @@ public class SearchBuilder {
|
||||||
/*
|
/*
|
||||||
* Now perform the search
|
* Now perform the search
|
||||||
*/
|
*/
|
||||||
TypedQuery<Long> query = myEntityManager.createQuery(outerQuery);
|
final TypedQuery<Long> query = myEntityManager.createQuery(outerQuery);
|
||||||
final Iterator<Long> results = query.getResultList().iterator();
|
|
||||||
final Set<Long> pidSet = new HashSet<Long>();
|
|
||||||
|
|
||||||
return new Iterator<Long>() {
|
return new Iterator<Long>() {
|
||||||
|
|
||||||
|
private final Set<Long> myPidSet = new HashSet<Long>();
|
||||||
|
private Iterator<Long> myResultsIterator;
|
||||||
private Long myNext;
|
private Long myNext;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1578,10 +1579,13 @@ public class SearchBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fetchNext() {
|
private void fetchNext() {
|
||||||
|
if (myResultsIterator == null) {
|
||||||
|
myResultsIterator = query.getResultList().iterator();
|
||||||
|
}
|
||||||
if (myNext == null) {
|
if (myNext == null) {
|
||||||
while (results.hasNext()) {
|
while (myResultsIterator.hasNext()) {
|
||||||
Long next = results.next();
|
Long next = myResultsIterator.next();
|
||||||
if (next != null && pidSet.add(next)) {
|
if (next != null && myPidSet.add(next)) {
|
||||||
myNext = next;
|
myNext = next;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1604,45 +1608,42 @@ public class SearchBuilder {
|
||||||
private static Long NO_MORE = Long.valueOf(-1);
|
private static Long NO_MORE = Long.valueOf(-1);
|
||||||
|
|
||||||
public IBundleProvider search(final SearchParameterMap theParams) {
|
public IBundleProvider search(final SearchParameterMap theParams) {
|
||||||
myParams = theParams;
|
// myParams = theParams;
|
||||||
StopWatch w = new StopWatch();
|
// StopWatch w = new StopWatch();
|
||||||
|
//
|
||||||
if (theParams.isLoadSynchronous()) {
|
// if (theParams.isLoadSynchronous()) {
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
mySearchEntity = new Search();
|
// mySearchEntity = new Search();
|
||||||
mySearchEntity.setUuid(UUID.randomUUID().toString());
|
// mySearchEntity.setUuid(UUID.randomUUID().toString());
|
||||||
mySearchEntity.setCreated(new Date());
|
// mySearchEntity.setCreated(new Date());
|
||||||
mySearchEntity.setTotalCount(-1);
|
// mySearchEntity.setTotalCount(-1);
|
||||||
mySearchEntity.setPreferredPageSize(myParams.getCount());
|
// mySearchEntity.setPreferredPageSize(myParams.getCount());
|
||||||
mySearchEntity.setSearchType(myParams.getEverythingMode() != null ? SearchTypeEnum.EVERYTHING : SearchTypeEnum.SEARCH);
|
// mySearchEntity.setSearchType(myParams.getEverythingMode() != null ? SearchTypeEnum.EVERYTHING : SearchTypeEnum.SEARCH);
|
||||||
mySearchEntity.setLastUpdated(myParams.getLastUpdated());
|
// mySearchEntity.setLastUpdated(myParams.getLastUpdated());
|
||||||
mySearchEntity.setResourceType(myResourceName);
|
// mySearchEntity.setResourceType(myResourceName);
|
||||||
|
//
|
||||||
for (Include next : myParams.getIncludes()) {
|
// for (Include next : myParams.getIncludes()) {
|
||||||
mySearchEntity.getIncludes().add(new SearchInclude(mySearchEntity, next.getValue(), false, next.isRecurse()));
|
// mySearchEntity.getIncludes().add(new SearchInclude(mySearchEntity, next.getValue(), false, next.isRecurse()));
|
||||||
}
|
// }
|
||||||
for (Include next : myParams.getRevIncludes()) {
|
// for (Include next : myParams.getRevIncludes()) {
|
||||||
mySearchEntity.getIncludes().add(new SearchInclude(mySearchEntity, next.getValue(), true, next.isRecurse()));
|
// mySearchEntity.getIncludes().add(new SearchInclude(mySearchEntity, next.getValue(), true, next.isRecurse()));
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
List<Long> firstPage = loadSearchPage(theParams, 0, 999);
|
// List<Long> firstPage = loadSearchPage(theParams, 0, 999);
|
||||||
mySearchEntity.setTotalCount(firstPage.size());
|
// mySearchEntity.setTotalCount(firstPage.size());
|
||||||
|
//
|
||||||
myEntityManager.persist(mySearchEntity);
|
// myEntityManager.persist(mySearchEntity);
|
||||||
for (SearchInclude next : mySearchEntity.getIncludes()) {
|
// for (SearchInclude next : mySearchEntity.getIncludes()) {
|
||||||
myEntityManager.persist(next);
|
// myEntityManager.persist(next);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
IBundleProvider retVal = doReturnProvider();
|
// IBundleProvider retVal = doReturnProvider();
|
||||||
|
//
|
||||||
ourLog.info("Search initial phase completed in {}ms", w);
|
// ourLog.info("Search initial phase completed in {}ms", w);
|
||||||
return retVal;
|
// return retVal;
|
||||||
}
|
return null;
|
||||||
|
|
||||||
public List<Long> loadSearchPage(SearchParameterMap theParams, int theFromIndex, int theToIndex) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// public IBundleProvider loadPage(SearchParameterMap theParams, int theFromIndex, int theToIndex) {
|
// public IBundleProvider loadPage(SearchParameterMap theParams, int theFromIndex, int theToIndex) {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package ca.uhn.fhir.jpa.search;
|
||||||
|
|
||||||
|
public class ISearchCoordinatorSvc {
|
||||||
|
|
||||||
|
}
|
|
@ -125,15 +125,15 @@ public final class PersistedJpaBundleProvider implements IBundleProvider {
|
||||||
// List<Long> pidsSubList = sb.loadSearchPage(parameterMap, theFromIndex, theToIndex);());
|
// List<Long> pidsSubList = sb.loadSearchPage(parameterMap, theFromIndex, theToIndex);());
|
||||||
List<Long> pidsSubList = null;
|
List<Long> pidsSubList = null;
|
||||||
|
|
||||||
Set<Long> revIncludedPids = new HashSet<Long>();
|
Set<Long> includedPids = new HashSet<Long>();
|
||||||
if (mySearchEntity.getSearchType() == SearchTypeEnum.SEARCH) {
|
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
|
// Execute the query and make sure we return distinct results
|
||||||
List<IBaseResource> resources = new ArrayList<IBaseResource>();
|
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;
|
return resources;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue