Reduce DB roundtrips for revincludes (#1937)
* Reduce DB roundtrips for revincludes * Add changelog
This commit is contained in:
parent
f88298a1fb
commit
6825d2fcf0
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
type: perf
|
||||||
|
issue: 1937
|
||||||
|
title: Due to an inefficient SQL statement when performing searches with large numbers of _revincludes where the resources
|
||||||
|
have tags, a large number of database roundtrips were produced when searching. This has been streamlined, greatly improving
|
||||||
|
the response times for some searches.
|
|
@ -32,7 +32,7 @@ import ca.uhn.fhir.jpa.model.entity.ResourceTag;
|
||||||
public interface IResourceTagDao extends JpaRepository<ResourceTag, Long> {
|
public interface IResourceTagDao extends JpaRepository<ResourceTag, Long> {
|
||||||
@Query("" +
|
@Query("" +
|
||||||
"SELECT t FROM ResourceTag t " +
|
"SELECT t FROM ResourceTag t " +
|
||||||
"INNER JOIN TagDefinition td ON (td.myId = t.myTagId) " +
|
"INNER JOIN FETCH t.myTag td " +
|
||||||
"WHERE t.myResourceId in (:pids)")
|
"WHERE t.myResourceId in (:pids)")
|
||||||
Collection<ResourceTag> findByResourceIds(@Param("pids") Collection<Long> pids);
|
Collection<ResourceTag> findByResourceIds(@Param("pids") Collection<Long> pids);
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,13 @@ import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.util.SqlQuery;
|
import ca.uhn.fhir.jpa.util.SqlQuery;
|
||||||
import ca.uhn.fhir.jpa.util.TestUtil;
|
import ca.uhn.fhir.jpa.util.TestUtil;
|
||||||
|
import ca.uhn.fhir.rest.api.SortSpec;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.r4.model.Bundle;
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
|
import org.hl7.fhir.r4.model.CareTeam;
|
||||||
import org.hl7.fhir.r4.model.CodeSystem;
|
import org.hl7.fhir.r4.model.CodeSystem;
|
||||||
import org.hl7.fhir.r4.model.DateTimeType;
|
import org.hl7.fhir.r4.model.DateTimeType;
|
||||||
import org.hl7.fhir.r4.model.IdType;
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
|
@ -538,6 +540,53 @@ public class FhirResourceDaoR4QueryCountTest extends BaseJpaR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchOnReverseInclude() {
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.getMeta().addTag("http://system", "value1", "display");
|
||||||
|
patient.setId("P1");
|
||||||
|
patient.getNameFirstRep().setFamily("FAM1");
|
||||||
|
myPatientDao.update(patient);
|
||||||
|
|
||||||
|
patient = new Patient();
|
||||||
|
patient.setId("P2");
|
||||||
|
patient.getMeta().addTag("http://system", "value1", "display");
|
||||||
|
patient.getNameFirstRep().setFamily("FAM2");
|
||||||
|
myPatientDao.update(patient);
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
CareTeam ct = new CareTeam();
|
||||||
|
ct.setId("CT1-" + i);
|
||||||
|
ct.getMeta().addTag("http://system", "value11", "display");
|
||||||
|
ct.getSubject().setReference("Patient/P1");
|
||||||
|
myCareTeamDao.update(ct);
|
||||||
|
|
||||||
|
ct = new CareTeam();
|
||||||
|
ct.setId("CT2-" + i);
|
||||||
|
ct.getMeta().addTag("http://system", "value22", "display");
|
||||||
|
ct.getSubject().setReference("Patient/P2");
|
||||||
|
myCareTeamDao.update(ct);
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchParameterMap map = SearchParameterMap
|
||||||
|
.newSynchronous()
|
||||||
|
.addRevInclude(CareTeam.INCLUDE_SUBJECT)
|
||||||
|
.setSort(new SortSpec(Patient.SP_NAME));
|
||||||
|
|
||||||
|
myCaptureQueriesListener.clear();
|
||||||
|
IBundleProvider outcome = myPatientDao.search(map);
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(outcome), containsInAnyOrder(
|
||||||
|
"Patient/P1", "CareTeam/CT1-0", "CareTeam/CT1-1","CareTeam/CT1-2",
|
||||||
|
"Patient/P2", "CareTeam/CT2-0", "CareTeam/CT2-1","CareTeam/CT2-2"
|
||||||
|
));
|
||||||
|
|
||||||
|
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
|
||||||
|
assertEquals(4, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size());
|
||||||
|
assertEquals(0, myCaptureQueriesListener.getInsertQueriesForCurrentThread().size());
|
||||||
|
assertEquals(0, myCaptureQueriesListener.getUpdateQueriesForCurrentThread().size());
|
||||||
|
assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionWithMultipleReferences() {
|
public void testTransactionWithMultipleReferences() {
|
||||||
Bundle input = new Bundle();
|
Bundle input = new Bundle();
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class ResourceTag extends BaseTag {
|
||||||
@Column(name = "PID")
|
@Column(name = "PID")
|
||||||
private Long myId;
|
private Long myId;
|
||||||
|
|
||||||
@ManyToOne(cascade = {})
|
@ManyToOne(cascade = {}, fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_RESTAG_RESOURCE"))
|
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_RESTAG_RESOURCE"))
|
||||||
private ResourceTable myResource;
|
private ResourceTable myResource;
|
||||||
|
|
||||||
|
|
|
@ -159,8 +159,9 @@ public class SearchParameterMap implements Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addRevInclude(Include theInclude) {
|
public SearchParameterMap addRevInclude(Include theInclude) {
|
||||||
getRevIncludes().add(theInclude);
|
getRevIncludes().add(theInclude);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addUrlIncludeParams(StringBuilder b, String paramName, Set<Include> theList) {
|
private void addUrlIncludeParams(StringBuilder b, String paramName, Set<Include> theList) {
|
||||||
|
@ -268,8 +269,9 @@ public class SearchParameterMap implements Serializable {
|
||||||
return mySort;
|
return mySort;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSort(SortSpec theSort) {
|
public SearchParameterMap setSort(SortSpec theSort) {
|
||||||
mySort = theSort;
|
mySort = theSort;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue