Эта статья морально устарела :( . Приглашаю продолжить ваше знакомство с Salesforce на нашем Форуме!
Следить за объемом обрабатываемых данных это одно из главных правил программирования в любом языке, и на любой платформа. Проблема Salesforce в том, что эти объемы данных здесь жестко ограничены. Я уже поднимал эту тему, но недавние проблемы, всплывшие у одного заказчика, опять заставили взглянуть в эту сторону. Приведу здесь наиболее узкие места, которые могут могут выстрелить в любую минуту, если не предпринять вовремя меры по ограничению объема обрабатываемых данных.
:) Мне это напомнило старые добрые времена, когда мы с друзьями на Speccy соревновались кто запихнет какой-нибудь визуальный эффект в 100 байт кода на assembler. Тогда борьба шла за каждый байт. Было весело. Ну а сегодня это уже серьезная тема, денежная, но salesforce заставляет поломать голову над реализацией того или иного функционала.
Давайте немного поэкспериментируем в Developer Console и понаблюдаем за цифрами.
В Developer Console можно попасть из меню в правом верхнем углу экрана (там где имя вашего пользователя) или из Setup->Create->Classes->Developer Console Button. В самой консоли вверху есть кнопка Execute. Нажимаем ее и в открывшемся окне вводим свой apex code и запускаем на выполнение. (немного об этом я писал здесь). Дальше смотрим лог и считаем цифры.
Вот пример идеального отчета по затраченным лимитам для одной строки кода:
Integer i = 12;
Number of SOQL queries: 0 out of 100
Number of query rows: 0 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 0 out of 150
Number of DML rows: 0 out of 10000
Number of code statements: 1 out of 200000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 10
Number of Email Invocations: 0 out of 10
Number of fields describes: 0 out of 100
Number of record type describes: 0 out of 100
Number of child relationships describes: 0 out of 100
Number of picklist describes: 0 out of 100
Number of future calls: 0 out of 10
for (Integer i=0; i++; i<101){
List<Contact> contacts = [SELECT Id FROM Contact LIMIT 1];
}
04:51:13.262 (262903000)|FATAL_ERROR|System.LimitException: Too many SOQL queries: 101
AnonymousBlock: line 2, column 1
04:51:13.774 (263094000)|CUMULATIVE_LIMIT_USAGE
04:51:13.774|LIMIT_USAGE_FOR_NS|(default)|
Number of SOQL queries: 101 out of 100 ******* CLOSE TO LIMIT
Number of query rows: 100 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 0 out of 150
Number of DML rows: 0 out of 10000
Number of code statements: 102 out of 200000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 10
Number of Email Invocations: 0 out of 10
Number of fields describes: 0 out of 100
Number of record type describes: 0 out of 100
Number of child relationships describes: 0 out of 100
Number of picklist describes: 0 out of 100
Number of future calls: 0 out of 10
List<Account> Accounts = new List<Account>();
List<Contact> Contacts = new List<Contact>();
for (Integer i=0; i<100; i++){
Accounts.add(new Account(Name='name'+i));
Contacts.add(new Contact(FirstName='name'+i, AccountID = null));
}
Integer CodeStatementsStart = Limits.getScriptStatements();
for (Account acc : Accounts) {
Integer i = 0;
for (Contact con : Contacts) {
//system.debug('x - '+Limits.getScriptStatements());
if (con.AccountID == acc.Id) {
i++;
}
}
system.debug('account ('+acc.Id+') has '+i+' contacts');
}
Integer CodeStatementsTotal = Limits.getScriptStatements() - CodeStatementsStart;
SYSTEM.DEBUG('CodeStatementsTotal - '+CodeStatementsTotal);
CodeStatementsStart = Limits.getScriptStatements();
Map<Id, Integer> AccountId_TotalContacts = new Map<Id, Integer>();
for (Contact con : Contacts){
AccountId_TotalContacts.put(con.AccountID, AccountId_TotalContacts.get(con.AccountID) == null ? 0 : AccountId_TotalContacts.get(con.AccountID)+1);
}
for (Id accId : AccountId_TotalContacts.keySet()) {
system.debug('account ('+accId+') has '+AccountId_TotalContacts.get(accId)+' contacts');
}
CodeStatementsTotal = Limits.getScriptStatements() - CodeStatementsStart;
SYSTEM.DEBUG('CodeStatementsTotal2- '+CodeStatementsTotal);