From 8e87e344dc41601e2d8cc68e350d5f3f61ca1c00 Mon Sep 17 00:00:00 2001
From: cramakri <cramakri>
Date: Tue, 4 May 2010 08:55:28 +0000
Subject: [PATCH] LMS-1153 Improved performance of query by using a sub-select
 to reduce the number of joins.

SVN: 15741
---
 .../authorization/PredicateExecutor.java      | 33 +++++++++++--
 .../DataSetCodeCollectionPredicate.java       |  5 --
 .../generic/shared/dto/DataSetAccessPE.java   | 46 +++----------------
 3 files changed, 36 insertions(+), 48 deletions(-)

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/PredicateExecutor.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/PredicateExecutor.java
index e5b64cd5724..32a166434b6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/PredicateExecutor.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/PredicateExecutor.java
@@ -16,6 +16,7 @@
 
 package ch.systemsx.cisd.openbis.generic.server.authorization;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -272,13 +273,37 @@ public final class PredicateExecutor
         @SuppressWarnings("unchecked")
         public List<DataSetAccessPE> tryGetDatasetCollectionAccessData(List<String> dataSetCodes)
         {
+
             Session sess = daoFactory.getSessionFactory().getCurrentSession();
             Query query = sess.getNamedQuery(DataSetAccessPE.DATASET_ACCESS_QUERY_NAME);
             query = query.setReadOnly(true);
-            List<DataSetAccessPE> results =
-                    query.setParameterList(DataSetAccessPE.DATA_SET_CODES_PARAMETER_NAME,
-                            dataSetCodes).list();
-            return results;
+
+            // WORKAROUND Problem in Hibernate when the number of data set codes > 1000
+            // Though this query runs quickly within the pgadmin tool, even for large numbers of
+            // data set codes, Hibernate becomes *very* slow when the size of the data set codes
+            // exceeds 1000. For that reason, break down the query into smaller sections and
+            // reassemble the results.
+            ArrayList<DataSetAccessPE> fullResults = new ArrayList<DataSetAccessPE>();
+
+            int size = dataSetCodes.size();
+            // blockSize is a magic number -- I don't know what the optimal value is, but execution
+            // speed slows down if the blockSize > 1999
+            int blockSize = 999;
+            int start, end;
+
+            // Loop over the codes, one block at a time
+            for (start = 0, end = Math.min(start + blockSize, size); start < size; start = end, end =
+                    Math.min(start + blockSize, size))
+            {
+                List<String> sublist = dataSetCodes.subList(start, end);
+                query =
+                        query.setParameterList(DataSetAccessPE.DATA_SET_CODES_PARAMETER_NAME,
+                                sublist);
+                List<DataSetAccessPE> results = query.list();
+                fullResults.addAll(results);
+            }
+
+            return fullResults;
         }
 
         public GroupPE tryToGetGroup(SpaceOwnerKind kind, TechId techId)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/DataSetCodeCollectionPredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/DataSetCodeCollectionPredicate.java
index ed04d8340e0..dcd9c80d561 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/DataSetCodeCollectionPredicate.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/DataSetCodeCollectionPredicate.java
@@ -52,11 +52,6 @@ public class DataSetCodeCollectionPredicate extends AbstractGroupPredicate<List<
             return Status.OK;
         }
 
-        if (accessData.size() < dataSetCodes.size())
-        {
-            return Status.createError("Could not get access data for all datasets");
-        }
-
         for (DataSetAccessPE accessDatum : accessData)
         {
             String dbInstanceUUID = accessDatum.getDatabaseInstanceUuid();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetAccessPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetAccessPE.java
index 4a9ba8d9b27..479ca131da1 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetAccessPE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetAccessPE.java
@@ -31,25 +31,15 @@ import javax.persistence.SqlResultSetMapping;
 @Entity
 @SqlResultSetMapping(name = "implicit", entities = @EntityResult(entityClass = DataSetAccessPE.class))
 @NamedNativeQuery(name = "dataset_access", query = "select "
-        + "ds.id as dataSetId, ds.code as dataSetCode, g.code as groupCode, dbi.uuid as databaseInstanceUuid, dbi.code as databaseInstanceCode "
-        + "from "
-        + TableNames.DATA_TABLE
-        + " ds, "
-        + TableNames.EXPERIMENTS_TABLE
-        + " e, "
-        + TableNames.PROJECTS_TABLE
-        + " p, "
-        + TableNames.GROUPS_TABLE
-        + " g, "
-        + TableNames.DATABASE_INSTANCES_TABLE
-        + " dbi "
-        + "where ds.code in (:codes) and e.id = ds.expe_id and p.id = e.proj_id and g.id = p.grou_id and dbi.id = g.dbin_id", resultSetMapping = "implicit")
+        + "g.code as groupCode, dbi.uuid as databaseInstanceUuid, dbi.code as databaseInstanceCode "
+        + "from " + TableNames.PROJECTS_TABLE + " p, " + TableNames.GROUPS_TABLE + " g, "
+        + TableNames.DATABASE_INSTANCES_TABLE + " dbi " + "where p.id in "
+        + "(select e.proj_id from " + TableNames.DATA_TABLE + " ds, "
+        + TableNames.EXPERIMENTS_TABLE + " e "
+        + "where ds.code in (:codes) and ds.expe_id = e.id group by e.proj_id) "
+        + "and p.grou_id = g.id and dbi.id = g.dbin_id", resultSetMapping = "implicit")
 public class DataSetAccessPE
 {
-    private String dataSetId;
-
-    private String dataSetCode;
-
     private String groupCode;
 
     private String databaseInstanceUuid;
@@ -68,24 +58,12 @@ public class DataSetAccessPE
             String databaseInstanceCode)
     {
         DataSetAccessPE newMe = new DataSetAccessPE();
-        newMe.setDataSetId(dataSetId);
-        newMe.setDataSetCode(dataSetCode);
         newMe.setGroupCode(groupCode);
         newMe.setDatabaseInstanceUuid(databaseInstanceUuid);
         newMe.setDatabaseInstanceCode(databaseInstanceCode);
         return newMe;
     }
 
-    void setDataSetId(String dataSetId)
-    {
-        this.dataSetId = dataSetId;
-    }
-
-    void setDataSetCode(String dataSetCode)
-    {
-        this.dataSetCode = dataSetCode;
-    }
-
     void setGroupCode(String groupCode)
     {
         this.groupCode = groupCode;
@@ -102,16 +80,6 @@ public class DataSetAccessPE
     }
 
     @Id
-    public String getDataSetId()
-    {
-        return dataSetId;
-    }
-
-    public String getDataSetCode()
-    {
-        return dataSetCode;
-    }
-
     public String getGroupCode()
     {
         return groupCode;
-- 
GitLab