memesh
Share on facebook
Share on twitter
Share on linkedin
Diurno

O frustrante caso de estouro de consultas SOQL no Salesforce e como contornar

memesh

Assim como quando seu irmão mais novo começa a fazer download de um jogo imenso e isso diminui drasticamente o desempenho da sua conexão á internet, aconteceria se todos os usuários de um mesmo conjunto de servidores em nuvem fizessem requisições pesadas e não-otimizadas ao mesmo tempo…queda de desempenho e estresse para todos!

No último post exploramos a importância de se utilizar de recursos do tipo “eager loading” para popular objetos. Simplificando, seria sempre evitar consultas ao banco de dados dentro de um loop. Um caso onde essa técnica não só representa uma maneira de otimização mas, também, uma questão de sobrevivência é no ambiente do Salesforce. Para os que têm alguma experiência com essa plataforma uma das primeiras lições aprendidas é: no Salesforce tudo tem limite.

salesproblem

Cada vez mais a programação na nuvem vem dominando o mercado e uma consequência direta disso é o compartilhamento de recursos. É como morar com várias outras pessoas na mesma casa: você não pode simplesmente chegar na cozinha e comer todos os pães, não é mesmo? Na nuvem ocorre situação semelhante, o Salesforce precisa controlar a disponibilidade do Servidor entre seus milhares de usuários para que todos tenham seus sistemas sempre disponíveis.

salesproblem2

Por causa disso ele praticamente obriga os desenvolvedores a elaborarem soluções otimizadas por meio de algumas limitações. Uma delas é a de consultas ao banco por transação, que é limitada em 100.

Digamos que exista uma rotina R que recebe uma lista de identificadores de contas para fazer alguma alteração nelas. Foi passado ao desenvolvedor que normalmente entre 5 e 10 contas vão ser coletadas por essa rotina. Para fazer as alterações precisamos recuperar o objeto Conta de cada um desses identificadores e o seguinte código foi desenvolvido:

AtualizaContas(List<id> lstIdContas)

{

Foreach(Id idConta in lstIdContas)

{

Conta conta = RecuperaConta(idConta);  //Consulta ao Banco

}

}

Alguns testes são feitos, a rotina sempre coleta entre 5 e 10 contas ou seja, no pior caso são feitas 10 consultas em uma transação. 10 consultas está bem longe do nosso limite de 100 certo? Alguns dias depois uma carga é feita no banco. 200 contas são importadas no sistema e todas são coletadas pela rotina….problema!! Estouramos nossa conta de 100 consultas com uma carga nem tão expressiva assim!  Isso significa que vamos ter que fazer a carga de 100 em 100 contas? Claro que não! Uma solução simples para isso é fazer o loop em memória. No nosso exemplo podemos sempre pegar essa lista de identificadores e obtermos todas as contas e alocar em memória, em uma Lista ou Map. O loop então seria feito assim:

AtualizaContas(List<id> lstIdContas)

{

Map<Conta, Id> mapContas = RecuperaMapContas(lstIdContas);  //Consulta ao Banco

Foreach(Id idConta in lstIdContas)

{

//Aqui podemos recuperar a conta do Map e fazer a lógica

}

}

Observe que não importa se tivermos uma lista de identificadores de 10 ou mil contas, a consulta ao banco será feita uma única vez. Bem melhor certo? Devemos ressaltar que otimização deve sempre ser feita dependendo da aplicação Se queremos recuperar somente uma conta de todas as contas disponíveis no sistema não vale a pena armazenar todas as contas em memória para depois escolher uma…bom senso é importante nesse caso!

Tem alguma dúvida sobre customização do Salesforce? Entre em contato com a gente.

Por: Ludmila Lopes e Jéssica Saliba.