Как сказал Дэвид в вышеприведенном комментарии, доступ довольно оптимизирован, как есть.
Если вы ищете дополнительную оптимизацию, я бы:
Переместите if(c.Request_for_Closure_Date__c!=null
и улучшите предложение WHERE (почему вы хотите получить некоторые Случаи, если пропустите их при обработке?). Так что-то вроде
SELECT Id,
(SELECT CaseId, Id, isCompleted...
FROM CaseMilestones
WHERE ...)
FROM Case
WHEREId IN :caseids AND Request_for_Closure_Date__c!=null
выбросить этот код. Если это только для system.debug - вы просто тратите время на вычисления.
Integer ms = Integer.valueOf((BusinessHours.diff(bh.id, ml.CompletionDate, c.Request_for_Closure_Date__c))/1000);
system.debug('Time@calculation'+ms);
Integer sec = ms;
Integer mns = sec/60;
integer days = mns / 60 / 24 ;
integer hours = (mns - days * 60 * 24) / 60 ;
integer mins = mns - days * 60 * 24 - hours * 60 ;
String timeSpentOnCase = days+'Days '+hours+'Hours '+mins+'Minutes'+sec+'Secs';
System.debug('Time'+timeSpentOnCase);
Если после этих двух оптимизаций у вас все еще есть проблемы с производительностью, вам, возможно, придется пересмотреть свою бизнес-логику и запрос. Гарантируется ли, что в каждом случае будет не более 1 этапа каждого типа?
Может быть, вам нужен подзапрос только с одним типом, который даст вам последний этап? Что-то вроде SELECT Id, (SELECT CompletionDate FROM CaseMilestones WHERE Type = 'x' ORDER BY CompletionDate DESC LIMIT 1) FROM Case
? Затем вы запускаете этот запрос для второго типа и процесса. Хорошо, тратит впустую 2 запроса, но гарантированно возвращает только несколько строк.
Или, может быть, вы можете полностью упростить этот код, выполнив что-то вроде
SELECT CaseId, MAX(CompletionDate) d, MilestoneType.Name t
FROM CaseMilestone
WHERE CaseId IN :... AND MilestoneType.Name IN :...
GROUP BY CaseId, MilestoneType.Name