I'm trying to refrain from doing a mass update directly through SQL and want to use X++ jobs to do it, but what I want to do is pretty darn slow.

I've got about 3500+ customer records (CustTable) to update, here's what I have:

static void fixCustLanguageId(Args _args)
{
    CustTable custTable;
    ;

    ttsbegin;

    try {

        update_recordset custTable
        setting
            LanguageId = 'fr'
        where custTable.AccountNum like 'LML*' && custTable.LanguageId == 'fr-ca';
        ttscommit;
        info('Done updating customers');
    }
    catch
    {
        ttsabort;
        error('Error updating customers');
    }


}

This is taking many hours to complete, is this normal ? Any way to achieve this faster ?

Thanks

有帮助吗?

解决方案 3

I ended up a while select forupdate since my case ended up involving much more logic than what I initially posted. Thanks anyways.

其他提示

Using update_recordset is the fasted. However, because the update() method of the custtable is overwritten, instead of making one call to sql, it is reverted to a call for each record. Moreover, the code that is on the update method is executed for all records.

If you don't want that and you only want to update the field without calling the update method, you can get around this by calling skipDataMethods(true), as shown here:

static void fixCustLanguageId(Args _args)
{
    CustTable custTable;

    try 
    {
        ttsbegin;
        custTable.skipDataMethods(true);

        update_recordset custTable
        setting
            LanguageId = 'fr'
        where custTable.AccountNum like 'LML*' && custTable.LanguageId == 'fr-ca';
        ttscommit;
        info('Done updating customers');
    }
    catch
    {
        error('Error updating customers');
    }
}

Using this code will be the fasted, but the code on the update method will not be executed. By the way, calling ttsabort in your catch is not needed, your transaction is automatically aborted.

An other thing that will cause update_recordset to be converted to record per record updates is when the database log is configured for that table in AX (see: http://technet.microsoft.com/en-us/library/dd362089.aspx). Deactivate this logging because it quite an impact on performance.

The 'problem' is that update_recordset takes care of your update() method on your CustTable records, i.e. for each affected record, the AOS has to call CustTable.update(). Due to this fact, the AOS will transform your update_recordset into something which is similar to a while select forUpdate.

For further information see here

A short overview about when the AOS fallbacks to this row-based mode and how to prevent the AOS from doing that is here

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top