Otimizar SOQL, o que eu ganho com isso?
Um dos grandes desafios de qualquer desenvolvedor Salesforce é fazer com que seu código não atinja nenhum limite, mas como nem tudo são flores na vida, acabamos enfrentando esse problema mais cedo ou mais tarde.
Há vários motivos que podem fazer a execução do seu código quebrar por atingir esses limites, alguns desses motivos são relacionados a queries SOQL, que podem estar demorando muito para executar ou trazer mais de 200 mil registros em uma única query, mas não se preocupe, estou escrevendo este artigo exatamente para mostrar formas de otimizar sua SOQL e evitar que estes erros ocorram.
Como avaliar o custo da query SOQL
Primeiro precisamos entender o que está sendo executado na nossa query e para isso utilizamos o query plan no developer console. Para habilitá-lo, basta abrir o Developer Console e ir no menu Help > Preferences e marcar a opção Enable Query Plan
Depois, entre na aba Query Editor, coloque sua query e clique no botão Query Plan
Temos agora um passo a passo da nossa query e aqui vai uma explicação simples do que é cada um desses campos:
Cardinality: Quantos registros estão retornando naquela na operação
Fields: Qual campo está sendo usado
Leading Operation Type: Nome da operação executada.
Cost: Quanto custa para a SOQL ser executada, aqui e leitura é a seguinte… Está acima de 1, a query é muito abrangente e isso significa que leva mais tempo para ser executado, o contrário disso é, se estiver abaixo de 1 mais rápido sua query vai ser executada.
sObject Cardinality: Quantos registros existem no objeto
sObject Type: Qual objeto esta sendo usado na operação
Bom, acho que ficou claro que o campo cost é o mais importante a ser olhado, certo? Sim, mas recomendo olhar também o campo de cardinality porquê quando temos varias clausulas no where, cada um é mostrado em uma linha e neste campo conseguimos ver qual campo pode ser mais seletivo.
E o como devemos otimizar nossas SOQL? Colocando cláusulas mais seletivas para trazer exatamente o necessário, evitando longo processamento da query ou pelo estouro no limite de registros por query. Com isso trouxe algumas dicas para montar cláusulas mais seletivas.
Como deixar sua query mais eficiente
Começando com campos indexados, adicioná-los primeiro na sua cláusula where faz com que o TableScan já traga menos dados para depois aplicar os outros filtros, isso aumenta a performance da sua query. Todo objeto já tem alguns campos indexados por padrão, que são:
- Chave primárias como Id e Name
- campos de relacionamento( lookup e master-detail)
- O campo SystemModStamp
- Campos customizados do tipo externalId ou unique
Já pegando carona nos campos indexados, troque o campo LastModifiedDate pelo SystemModStamp nas cláusulas where, esses campos fazem essencialmente a mesma coisa, mas com duas diferenças simples, enquanto o LastModifiedDate guarda somente a data da última alteração quando feito por um usuário, o SystemModStamp abrange atualizações feitas por process builder, triggers, etc. E a outra diferença que o SystemModStamp é somente leitura, o que faz dele um campo indexado e por este motivo sua query ganha performance
Agora chegou a vez dos formula fields, evite-os nas cláusulas o máximo que puder porque para cada registro a fórmula vai ser recalculada, degradando bastante seu select caso o objeto tenha muitos registros.
E por último e não importante, o operador OR, NOT e !=, sim, eles podem estar deixando sua query lenta, porque para OR não deixe sua query lenta, todos os campos precisam ser indexados e caso tenham campos de outros objetos, talvez não sejam indexados. Not e != fazem como que o campo indexado não seja utilizado no query optimizer
Outras melhorias que otimizam a query indiretamente
Além dessas dicas, tem outras coisas que podemos fazer para ajudar a otimizar as queries, como avaliar se as sharing rules estão restringindo o suficiente e de forma correta os dados da org.
Utilizar with sharing nas classes, porque não adianta nada ter as sharing rules corretas se não tem efeito dentro do código e pra fechar este artigo.
Skinny Tables, que é um espelho do seu objeto que contém todos os campos que não precisam de dados de outros objetos, sejam eles standard ou custom, e como isso ajuda na performance?
Por baixo dos panos, qualquer objeto é separado em dois “sub-objetos”, um com os campos standards e outro com os campos custom e isso pode trazer certa lentidão, então é criado um terceiro objeto não visível para o usuário, que é usado na query quando somente campos de dentro deste objeto são adicionados na query, porém novamente como nem tudo são flores, skinny table tem limitações que são:
- Toda campo novo criado no objeto não é criado automaticamente no skinny table, é preciso abrir um case para a salesforce realizar o update da skinny table
- Só podem tem no máximo 100 colunas ( campos), e além disso… Se seu objeto tem mais de 100 campos, seria melhor dar uma olhada para ser se não está sendo super utilizado
- Para full sandboxes, as skinny tables são copiadas de prod, porém para as outras é preciso entrar em contato com a Salesforce para realizar esta operação
Então pessoal saibam quando criar uma skinny table porque podem acabar criando outros problemas ao invés de resolver um. E é isso por isso pessoal, acho que ficou longo o artigo mas consegui abordar tudo que acho interessante para este problema, espero que vocês tenham gostado e até uma próxima :)