AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 15.12.2011, 00:09   #1  
glibs is offline
glibs
Member
Сотрудники компании It Box
Most Valuable Professional
Лучший по профессии 2011
Лучший по профессии 2009
 
4,942 / 911 (40) +++++++
Регистрация: 10.06.2002
Адрес: I am from Kyiv, Ukraine. Now I am in Moscow. For private contacts: glibs@hotmail.com
Джоб
X++:
static void glibs(Args _args)
{
    TmpAccountSum       tmpAccountSum1,
                        tmpAccountSum2;
    Counter             i;
    FreeText            text;
    Counter             startTime;

    #Define.cycles(1000)
    ;

    startTime = WinAPI::getTickCount();
    for (i = 0; i <= #cycles; i++)
    {
        tmpAccountSum1.clear();
        tmpAccountSum2.clear();
        text = int2str(i);
        tmpAccountSum1.AccountNum = strrep("0", 20 - strlen(text)) + text;
        tmpAccountSum2.AccountNum = strrep("0", 20 - strlen(text)) + text;
        tmpAccountSum1.Balance01 = 999999 * 888888;
        tmpAccountSum2.Balance01 = 999999 * 888888;
        tmpAccountSum1.Balance02 = 999999 * 888888;
        tmpAccountSum2.Balance02 = 999999 * 888888;
        tmpAccountSum1.Balance03 = 999999 * 888888;
        tmpAccountSum2.Balance03 = 999999 * 888888;
        tmpAccountSum1.Balance04 = 999999 * 888888;
        tmpAccountSum2.Balance04 = 999999 * 888888;
        tmpAccountSum1.Balance05 = 999999 * 888888;
        tmpAccountSum2.Balance05 = 999999 * 888888;
        tmpAccountSum1.Balance06 = 999999 * 888888;
        tmpAccountSum2.Balance06 = 999999 * 888888;
        tmpAccountSum1.Balance07 = 999999 * 888888;
        tmpAccountSum2.Balance07 = 999999 * 888888;
        tmpAccountSum1.Balance10 = 999999 * 888888;
        tmpAccountSum2.Balance10 = 999999 * 888888;
        tmpAccountSum1.TaxCode = "XXXXXXXXXXXXXXXXXXXX";
        tmpAccountSum2.TaxCode = "XXXXXXXXXXXXXXXXXXXX";
        tmpAccountSum1.CurrencyCode = "XXX";
        tmpAccountSum2.CurrencyCode = "XXX";
        tmpAccountSum1.Posting = 1;
        tmpAccountSum2.Posting = 1;
        tmpAccountSum1.Dimension[1] = "XXXXXXXXXXXXXXXXXXXX";
        tmpAccountSum2.Dimension[1] = "XXXXXXXXXXXXXXXXXXXX";
        tmpAccountSum1.Dimension[2] = "XXXXXXXXXXXXXXXXXXXX";
        tmpAccountSum2.Dimension[2] = "XXXXXXXXXXXXXXXXXXXX";
        tmpAccountSum1.Dimension[3] = "XXXXXXXXXXXXXXXXXXXX";
        tmpAccountSum2.Dimension[3] = "XXXXXXXXXXXXXXXXXXXX";
        tmpAccountSum1.OperationsTax = 1;
        tmpAccountSum2.OperationsTax = 1;
        tmpAccountSum1.TransDate = today();
        tmpAccountSum2.TransDate = today();
        tmpAccountSum1.Txt = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +
                             "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +
                             "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +
                             "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        tmpAccountSum2.Txt = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +
                             "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +
                             "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +
                             "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        tmpAccountSum1.SortDate = today();
        tmpAccountSum2.SortDate = today();
        tmpAccountSum1.Balance01Cur = 999999 * 888888;
        tmpAccountSum2.Balance01Cur = 999999 * 888888;
        tmpAccountSum1.Qty01 = 999999 * 888888;
        tmpAccountSum2.Qty01 = 999999 * 888888;
        tmpAccountSum1.Qty02 = 999999 * 888888;
        tmpAccountSum2.Qty02 = 999999 * 888888;
        tmpAccountSum1.Qty03 = 999999 * 888888;
        tmpAccountSum2.Qty03 = 999999 * 888888;
        tmpAccountSum1.Voucher = "XXXXXXXXXXXXXXXXXXXX";
        tmpAccountSum2.Voucher = "XXXXXXXXXXXXXXXXXXXX";
        tmpAccountSum1.insert();
        tmpAccountSum2.insert();
    }
    info (strfmt("%1", (WinAPI::getTickCount() - startTime) / 1000));

    startTime = WinAPI::getTickCount();
    i = 0;
    while select tmpAccountSum1
    join tmpAccountSum2
        where tmpAccountSum1.AccountNum == tmpAccountSum2.AccountNum
    {
        text = tmpAccountSum1.Voucher + tmpAccountSum2.Voucher;
        i++;
    }
    info (strfmt("%1", i));
    info (strfmt("%1", (WinAPI::getTickCount() - startTime) / 1000));
    
    startTime = WinAPI::getTickCount();
    i = 0;
    while select tmpAccountSum1
    {
        while select tmpAccountSum2
            where tmpAccountSum2.AccountNum == tmpAccountSum1.AccountNum
        {
            text = tmpAccountSum1.Voucher + tmpAccountSum2.Voucher;
            i++;
        }
    }
    info (strfmt("%1", i));
    info (strfmt("%1", (WinAPI::getTickCount() - startTime) / 1000));

}
__________________
С уважением,
glibs®
За это сообщение автора поблагодарили: mazzy (5), sukhanchik (3), Logger (15).
Старый 15.12.2011, 00:25   #2  
glibs is offline
glibs
Member
Сотрудники компании It Box
Most Valuable Professional
Лучший по профессии 2011
Лучший по профессии 2009
 
4,942 / 911 (40) +++++++
Регистрация: 10.06.2002
Адрес: I am from Kyiv, Ukraine. Now I am in Moscow. For private contacts: glibs@hotmail.com
Для тех кто не читает Х++. Остальные могут вместо этого просто прочитать код джоба
Для тех кто не понимает по Х++совски.

Эксперимент проводится на таблице TmpAccountSum, которую можно найти в АОТ в стандартной поставке. Это временная таблица. В ней есть несколько десятков полей различного вида (точнее, зазличных типов данных). Подробнее вы можете познакомиться с ней открыв АОТ.

В начале джоба написан код, который создает два экземпляра этой таблицы и заполняет их откровенным хламом (левыми данными).

Оба экземпляра заполняются абсолютно одинаковыми данными лишенными какого либо смысла. В этом нет никакой причины кроме лени и рационализма. Единственная цель которая пресдедовалась — чтобы все поля заполнить максимальным количеством символов, которые они могут вместить (чтобы каждая запись занимала как можно больше места на диске). Для показательности.

И только одно поле я заполнил немного интеллектуальнее. TmpAccountSum.AccountNum. Оно содержит порядковый номер записи переведенный в целочисленное строковое значение и добивается до максимальной длинны поля лидирующими нулями.

Такм образом TmpAccountSum.AccountNum содержит некий уникальный искусственно созданный ключ (на уровне структуры данных TmpAccountSum.AccountNum уникальным не является).

В результате TmpAccountSum.AccountNum заполняется примерно так:
00000000000000000000
00000000000000000001
00000000000000000002
00000000000000000003
и т.д.

Количество создаваемых строк задается в макросе #Define.cycles(1000) в конце списка определения переменных в джобе.

Суть эксперимента

В джобе написаны два блока кода. Они абсолютно равнозначны.

В первом блоке оба экземпляра временных таблиц джоинятся друг к другу по полю AccountNum.

Во втором блоке делается перебор записей в первом экземпляре в цикле и для каждой записи первого экземпляра перебираются все записи второго экземпляра, AccountNum которых равен AccountNum первого экземпляра. Короче, тот же джоин что и в первом случае, но реализованный через вложенный цикл.

Поскольку в поле AccountNum данные искусственно записываются уникальные, то первой записи первого экземпляра временной таблицы соответствует первая запись второго экземпляра временной таблицы. И т.д.

То есть в результате выборки данные не мультиплицируются. Количество строк в результате выборки будет равно количеству записей в каждой таблице.

Сделано это специально, чтобы размер выборки был небольшим.

Итак...
__________________
С уважением,
glibs®

Последний раз редактировалось sukhanchik; 15.12.2011 в 00:46.
За это сообщение автора поблагодарили: sukhanchik (2).
Старый 15.12.2011, 00:58   #3  
glibs is offline
glibs
Member
Сотрудники компании It Box
Most Valuable Professional
Лучший по профессии 2011
Лучший по профессии 2009
 
4,942 / 911 (40) +++++++
Регистрация: 10.06.2002
Адрес: I am from Kyiv, Ukraine. Now I am in Moscow. For private contacts: glibs@hotmail.com
Результаты эксперимента: скорость джоин vs вложенный цикл
На 1000 записей в каждом экземпляре временной раблицы
=============================================

0.28 - Времы вставки по 1000 записей в каждый из экземпляров временных таблиц
1001 - Количество выбранных записей в первой выборке
8.53 - Время выборки с джоином временных таблиц
1001 - Количество выбранных записей во второй выборке
0.05 - Время выборки с вложенным циклом вместо равнозначного первой выборке джоина временных таблиц


На 2000 записей в каждом экземпляре временной раблицы (увеличиваем количество строк временной таблицы вдвое)
==============================================================
0.53 - время вставки возросло почти вдвое
2001 - записей стало пракически вдвое больше
33.11 - времы выборки с джоином увеличилось вчетверо
2001 - нечего комментировать
0.08 - время выборки с вложенным циклом увеличилось меньше чем вдвое


Попробуем 4000 записей в каждом экземпляре временной раблицы (увеличиваем количество строк временной таблицы вдвое)
==============================================================
1.09 - опять чуть меньше чем вдвое
4001 - очень ожидаемо
136.34 - снова чуть больше чем вчетверо
4001 - нечего комментировать
0.17 - тоже чуть больше чем вдвое


Первые выводы:
Время вставки растет почти прямо пропорционально количеству записей.
Время выборки с вложенным циклом также растет прямо пропорционально количеству записей во временных таблицах.
Время выборки с джоином растет пропорционально приросту количества записей в квадрате.

Складывается впетатление, что джоин тупо перебирает все записи первой таблицы и для каждой аписи перебирает все записи второй таблицы. А потом уже смотрит на условия джоина.

Но это еще не все...
__________________
С уважением,
glibs®

Последний раз редактировалось glibs; 15.12.2011 в 01:46.
Теги
временная таблица, оптимизация, полезное, производительность

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Как правильно именовать временные таблицы Владимир Максимов DAX: Программирование 22 17.05.2011 21:03
Временные таблицы и их временные файлы AraraT® DAX: Прочие вопросы 6 12.04.2010 00:39
Не страшно ли временные таблицы временно сделать постоянными? Gustav DAX: Программирование 11 09.02.2006 11:04
Временные таблицы vasiliy DAX: Программирование 6 09.11.2004 11:04
Временные таблицы в запросе Dron AKA andy DAX: Программирование 4 06.09.2002 12:14
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра
Комбинированный вид Комбинированный вид

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 03:06.