DML per SOQL Risultato + Limiti

Sep 01 2020

Sto cercando di interrogare l'elenco dei record, apportare modifiche e aggiornare lo stesso. Vedo due approcci qui:

Approccio 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;

Approccio 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)
    }
    
    
}

Domanda: l'approccio 2 è migliore poiché non sappiamo se la query restituisce più di 10.000 record. Inoltre possiamo risparmiare sulla dimensione dell'heap sul secondo approccio, sebbene sintatticamente sto facendo un DML in un ciclo

Risposte

4 sfdcfox Sep 01 2020 at 09:50

Poiché esiste un limite di 10.000 record per transazione , non importa se ti limiti a 10.000 record contemporaneamente. Sei ancora limitato a 10.000 righe. La tua strategia dovrebbe quindi essere più simile a "se più di 10000 righe, passa a un metodo accodabile o batchable".

Inoltre, le tue query sono limitate a sole 50.000 righe prima che venga violato un limite governor (di nuovo, per transazione , non solo per query), che generalmente si adatterà allo spazio heap a meno che tu non interroghi molti campi per oggetto, nel qual caso potresti desidera passare a una dimensione inferiore, ad esempio 1.000 righe per operazione DML.

In generale, se sei preoccupato per un grande disallineamento dei dati, attiva un batchable o un accodabile, altrimenti non preoccuparti delle differenze. Il metodo per l'elenco dei record è leggermente più efficiente, ma ciò che è ancora più veloce è utilizzare il primo metodo senza copiare i record:

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

Questo ciclo ha le migliori caratteristiche di prestazione, poiché eviti di riallocare eccessivamente l'heap. Vedi questa risposta , questa risposta , questa risposta , questa risposta , questa risposta (non mia), questa domanda (anche non mia), questa domanda (più ottimizzazione, non mia) e altre domande sulle prestazioni per più domande relative alle prestazioni.

Potresti notare alcune risposte contraddittorie; le caratteristiche esatte delle prestazioni di Salesforce tendono a cambiare nel tempo, quindi è consigliabile eseguire i propri test, ma ancora più importante, non preoccuparti delle micro-ottimizzazioni , potrebbe non avere importanza a lungo termine o potrebbe persino essere ottimizzato in una versione futura.

L'unica cosa che dovresti togliere da questa risposta è che il limite di 10k è un limite rigido, quindi devi essere pronto a diramare a un Queueable o Batchable per aggiornare più di 10k record se sei preoccupato per la possibilità.