Как пройти мимо регуляторов триггеров Salesforce

Я пытаюсь написать триггер «после обновления», который выполняет пакетное обновление всех дочерних записей только что обновленной записи. Это должно иметь возможность обрабатывать более 15 тысяч дочерних записей за раз. К сожалению, ограничение составляет 100, что намного ниже моих потребностей, что даже близко к приемлемому. Я не пробовал разбивать записи на пакеты по 100 штук в каждой, так как это все равно ограничит меня в 10 тыс. Обновлений на выполнение триггера. (Может быть, я мог бы просто соединить триггеры гирляндной цепью? Тьфу.)

Кто-нибудь знает, через какую серию обручей я могу перепрыгнуть, чтобы преодолеть это ограничение?

Изменить: я попытался вызвать следующую функцию @future в своем триггере, но она никогда не обновляет дочерние записи:

global class ParentChildBulkUpdater
{
    @future 
    public static void UpdateChildDistributors(String parentId) {
        Account[] children = [SELECT Id FROM Account WHERE ParentId = :parentId];

        for(Account child : children)
            child.Site = 'Bulk Updater Fired';
        update children;

    }
}

person Jake    schedule 08.04.2010    source источник
comment
Должно ли обновление дочерней записи происходить в той же транзакции?   -  person Adam Butler    schedule 09.04.2010
comment
@ Адам Нет, это не так. Это просто должно произойти в конце концов.   -  person Jake    schedule 09.04.2010


Ответы (6)


Хуже того, вы даже не сможете получить эти 15 тыс. Записей, потому что в триггере есть ограничение в 1000 строк (это масштабируется до количества строк, для которых вызывается триггер, но это, вероятно, не поможет)

Я думаю, ваш единственный способ сделать это - использовать тег @future - читайте об этом в документации. Это дает вам гораздо более высокие пределы. Хотя вы можете вызывать только определенное количество из них в день, поэтому вам может потребоваться каким-то образом отслеживать, какие родительские объекты обновляют их дочерние объекты, а затем обрабатывать это в автономном режиме.

Последним вариантом может быть использование API через какой-либо внешний инструмент. Но вам все равно придется убедиться, что все в вашем коде смешано.

Сначала я думал, что эти ограничения были драконовскими, но на самом деле вы можете сделать в них чертовски много, если правильно группируете вещи, мы регулярно обновляем 1000 строк из триггеров. И с архитектурной точки зрения, гораздо больше, и вы все равно говорите о пакетной обработке, которая обычно не активируется триггером. Одно можно сказать наверняка - они заставляют вас прыгать через обручи, чтобы сделать это.

person Codek    schedule 09.04.2010
comment
Я пробовал использовать метод @future, но, похоже, он не срабатывает в моей песочнице - как долго мне нужно ждать, пока они сработают? - person Jake; 09.04.2010
comment
@Jake По моему опыту, методы @future выполняются за несколько секунд. Проверьте настройки ›Мониторинг› Задания Apex, чтобы узнать, выполняются ли ваши. - person Adam Butler; 09.04.2010
comment
@ Adam / @ Codek, Кто-нибудь из вас может взглянуть на метод @future, который я поместил в основной пост? Есть ли причина, по которой дети не будут обновлять так, как я ожидал? - person Jake; 10.04.2010
comment
Чтобы обновление работало правильно, вам необходимо добавить столбец «Сайт» в оператор SOQL. Один из способов проверить что-то подобное - вызвать его вручную из системного журнала. - person Adam Butler; 11.04.2010
comment
Большое спасибо, вы очень помогли. Сейчас я собираюсь использовать внешний инструмент API и перейти к веб-сервису API, как только мы получим какой-то хостинг. - person Jake; 13.04.2010
comment
как было сказано, придерживайтесь API (если у вас так много обновлений). Пусть ваш триггер вызовет веб-службу для передачи некоторой информации внешнему приложению, использующему SFDC API. Просто не забудьте сгруппировать свои обновления в группы по 200 (я обнаружил, что они становятся больше, что может вызывать ошибки, или, по крайней мере, это было для меня). Нам регулярно приходится обновлять десятки тысяч записей (огромная организация), и это единственный разумный способ сделать это. - person Mike McMahon; 09.03.2012

Лучший (и самый простой) путь решения этой проблемы - использовать Batch Apex, вы можете создать пакетный класс и запустить его с помощью триггера. Как и @future, он работает в отдельном потоке, но может обрабатывать до 50 000 000 записей!

Вам нужно будет передать некоторую информацию вашему пакетному классу перед использованием database.executeBatch, чтобы у него был список родительских идентификаторов для работы, или вы могли бы просто получить все учетные записи, конечно;)

Я только что заметил, сколько лет этому вопросу, но, надеюсь, этот ответ поможет другим.

person Matt Lacey    schedule 04.05.2011

Я думаю, что Codek прав, переход по маршруту API / внешний инструмент - хороший способ. Ограничения регулятора по-прежнему применяются, но для вызовов API они гораздо менее строгие. Salesforce недавно обновила свой инструмент DataLoader, так что это может быть чем-то, на что стоит обратить внимание.

Еще вы можете попробовать использовать правило рабочего процесса с исходящим сообщением для вызова веб-службы на вашей стороне. Просто отправьте родительский объект и позвольте процессу на вашей стороне обрабатывать обновления дочерних записей через API. Одна вещь, о которой следует помнить об исходящих сообщениях, - лучше всего как-то поставить процесс в очередь на своей стороне и немедленно ответить Salesforce. В противном случае Salesforce повторно отправит сообщение.

person Adam Butler    schedule 09.04.2010
comment
Возможно, до этого дойдет ... Кстати, спасибо за предупреждение о немедленном ответе. - person Jake; 09.04.2010

@future не работает (вообще не обновляет записи)? Странный. Вы пробовали использовать свою функцию в автоматическом тесте? Он должен работать, и аннотацию следует игнорировать (во время теста она будет выполнена мгновенно, методы тестирования имеют более высокие пределы). Я предлагаю вам изучить это немного подробнее, это кажется лучшим решением того, чего вы хотите достичь.

Также - может быть, попытаться вызвать его из своего класса, а не из триггера?

Триггеры с последовательным соединением вместе не работают, я пробовал это раньше.

Вашим последним вариантом может быть пакетная Apex (из версии Winter'10, поэтому к настоящему времени она должна быть у всех организаций). Он предназначен для массовых задач обновления / проверки данных, которые вы обычно выполняете в обычных базах данных в ночное время (это можно запланировать). См. http://www.salesforce.com/community/winter10/custom-cloud/program-cloud-logic/batch-code.jsp и примечания к выпуску в формате PDF.

person eyescream    schedule 11.04.2010
comment
Вы можете объяснить: Daisy-chaining triggers together will not work, I've tried it in the past. - person Aequitas; 29.11.2019
comment
@Aequitas, вы понимаете, что этой ветке 9 лет? С тех пор лимиты были увеличены (у нас было обновлено 1K записей и не более 20 запросов); любой может использовать пакетную апекс, и у нас есть @ future, Continuation, Queueable тоже ... Может быть, опубликуйте новый вопрос с вашей проблемой. Я думаю, что тогда я имел в виду, что OP пытается обновить, скажем, 200 контактов, затем запрашивает триггер контакта, есть ли еще необработанные контакты для этого мастера, и запускает следующее обновление ... Ничего не изменится, у вас все еще будет 10K записи, обновленные за одну транзакцию, могут даже достичь лимита рекурсии (я думаю, 20 вызовов) - person eyescream; 29.11.2019

Я считаю, что в версии 18 API ограничение в 1000 было снято. (так говорится в документации, но в некоторых случаях я все еще достиг предела)

Таким образом, вы можете использовать пакетный апекс. С помощью одного оператора обновления APEX

Что-то вроде:

Список детей = новый список {};

for (childObect__c c: [ВЫБРАТЬ ....]) {

c.foo__c = 'бар';

children.add (c);

} update (children) ;;

Убедитесь, что вы увеличили размер своего тигра, также см. http://sfdc.arrowpointe.com/2008/09/13/bulkifying-a-trigger-an-example/

person Daveo    schedule 10.04.2010
comment
Я использовал триггер v18 и достиг предела в 400. Он уже разросся, так что у него был только один выбор и одно обновление. В полученной мной ошибке указывалось, что проблема связана с размером оператора DML. - person Jake; 10.04.2010
comment
Интересно, где ты это видишь? Документы здесь по-прежнему показывают, что ограничение составляет 1000: salesforce.com/us/developer/docs/apexcode/ Но также есть хорошие примечания по вершине пакетной обработки, которые могут быть подходящими для этого: na1.salesforce.com/help/doc/en/ - person Codek; 12.04.2010

Возможно, лучше изменить вашу модель данных. Подумайте о создании формулы для дочернего объекта, где вы получаете доступ к данным от родительского объекта. Вероятно, это было бы намного эффективнее.

person Hannes    schedule 13.02.2011