DML для SOQL Результат + пределы

Sep 01 2020

Я пытаюсь запросить список записей, внести изменения и обновить то же самое. Здесь я вижу два подхода:

Подход 1:

 List<Account> listOfAccToUpdate=new List<Account>();
for(Account acc: [SELECT field1 FROM Account WHERE Rba__c=true]){
    acc.field1=true;
    listOfAccToUpdate.add(acc);
}
update listOfAccToUpdate;

Подход 2:

List<Account> listOfAccToUpdate=new List<Account>();
for(List<Account> accList: [SELECT field1 FROM Account WHERE Rba__c=true]){
    for(Account acc: accList){
        acc.field1=true;
    }
    if(listOfAccToUpdate.size()+accList.size()<=10000){
        listOfAccToUpdate.addAll(accList);
    }
    else{
        update listOfAccToUpdate;
        listOfAccToUpdate.clear();
        listOfAccToUpdate.addAll(accList)
    }
    
    
}

Вопрос. Подход 2 лучше, поскольку мы не знаем, возвращает ли запрос более 10 тыс. Записей. Также мы можем сэкономить на размере кучи при втором подходе, хотя синтаксически я делаю DML в цикле

Ответы

4 sfdcfox Sep 01 2020 at 09:50

Поскольку существует ограничение в 10 000 записей на транзакцию , не имеет значения, ограничиваете ли вы себя 10 000 записей одновременно. Вы по-прежнему ограничены 10 000 строками. Таким образом, ваша стратегия должна быть больше похожа на «если больше 10000 строк, переходите к методам с возможностью очереди или пакетной передачи».

Кроме того, ваши запросы ограничены всего 50000 строками, прежде чем ограничение регулятора будет нарушено (опять же, для каждой транзакции , а не только для каждого запроса), что обычно умещается в пространстве кучи, если вы не запрашиваете много полей для каждого объекта, и в этом случае вы можете хотите перейти к меньшему размеру, например 1000 строк на операцию DML.

В общем, если вас беспокоит большой перекос данных, отключите пакетную или очередь, иначе не беспокойтесь о различиях. Метод for-record-list немного более эффективен, но еще быстрее - использовать первый метод без копирования записей:

 List<Account> listOfAccToUpdate=[SELECT field1 FROM Account WHERE Rba__c=true];
for(Account acc: listOfAccToUpdate){
    acc.field1=true;
}
update listOfAccToUpdate;

Этот цикл имеет лучшие характеристики производительности, так как вы избегаете чрезмерного перераспределения кучи. Смотрите этот ответ , этот ответ , этот ответ , этот ответ , этот ответ (не мое), этот вопрос (тоже не моя), этот вопрос (более оптимизация, а не моя), а также другие характеристики вопросов для более вопросов, связанных с производительностью.

Вы можете заметить несколько противоречивых ответов; точные характеристики производительности Salesforce имеют тенденцию меняться со временем, поэтому рекомендуется проводить собственное тестирование, но, что еще более важно, не беспокойтесь о микрооптимизации , это может не иметь значения в долгосрочной перспективе или даже может быть оптимизировано в будущем выпуске.

Единственное, что вы должны убрать из этого ответа, - это то, что ограничение в 10k является жестким, поэтому вы должны быть готовы перейти к Queueable или Batchable, чтобы обновить более 10k записей, если вас беспокоит такая возможность.