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> {
|
||||
@Query("" +
|
||||
"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)")
|
||||
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.util.SqlQuery;
|
||||
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.param.ReferenceParam;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
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.DateTimeType;
|
||||
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
|
||||
public void testTransactionWithMultipleReferences() {
|
||||
Bundle input = new Bundle();
|
||||
|
|
|
@ -42,7 +42,7 @@ public class ResourceTag extends BaseTag {
|
|||
@Column(name = "PID")
|
||||
private Long myId;
|
||||
|
||||
@ManyToOne(cascade = {})
|
||||
@ManyToOne(cascade = {}, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_RESTAG_RESOURCE"))
|
||||
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);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void addUrlIncludeParams(StringBuilder b, String paramName, Set<Include> theList) {
|
||||
|
@ -268,8 +269,9 @@ public class SearchParameterMap implements Serializable {
|
|||
return mySort;
|
||||
}
|
||||
|
||||
public void setSort(SortSpec theSort) {
|
||||
public SearchParameterMap setSort(SortSpec theSort) {
|
||||
mySort = theSort;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue