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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 05.04.2011, 20:24   #1  
Ivanhoe is offline
Ivanhoe
Участник
Аватар для Ivanhoe
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
4,143 / 2161 (81) +++++++++
Регистрация: 29.09.2005
Адрес: Санкт-Петербург
Коллеги, я не программист, но разве так нельзя?
X++:
while select table1
{
    i++;
    ttsbegin;

    table1.selectForUpdate(true);
    table1.reread();

    table1.Field1 = strfmt("Blah %1", i);
    table1.doupdate();
    ttscommit;
}
__________________
Ivanhoe as is..
Старый 05.04.2011, 21:12   #2  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,448 / 1789 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Ivanhoe Посмотреть сообщение
разве так нельзя?
Можно, но reread = дополнительный select, что может оказаться накладным. К слову сказать если гарантировать отсутствие конфликтов (например запускать обработку на свободной базе), то можно попробовать и без него , но это от лукавого .

Обнаруженное поведение while select'а - это явный баг. Есть ещё вариант попробовать переписать цикл с использованием select ... next. В принципе то же самое, только вид сбоку, но кто его знает ...
Старый 05.04.2011, 21:17   #3  
Hyper is offline
Hyper
Участник
Соотечественники
 
163 / 29 (1) +++
Регистрация: 09.10.2003
Цитата:
Сообщение от Ivanhoe Посмотреть сообщение
Коллеги, я не программист, но разве так нельзя?

Я пытаюсь избавиться от двух зол:
1) отдельный ttsbegin/ttscommit для каждой записи (из 700 000 в одной таблице)
2) единственный ttsbegin/ttscommit для всей таблицы (700 000 записей)

Оптимальным решением было бы разбить таблицу на, скажем, 70 кусков, т.е. изменить все записи за 70 транзакций.

Для таблиц с уникальным индексом по единственному полю я, вроде, решение нашел, завтра продолжу тестирование.

Для остальных, если не извращаться, надо будет выбрать (1) или (2).

При гипотетическом отсутствии других вариантов какой из этих двух вариантов будет оптимальнее, кто как думает?

Последний раз редактировалось Hyper; 05.04.2011 в 21:20.
Старый 05.04.2011, 21:57   #4  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,913 / 5736 (197) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Цитата:
Сообщение от Hyper Посмотреть сообщение
Оптимальным решением было бы разбить таблицу на, скажем, 70 кусков, т.е. изменить все записи за 70 транзакций.
Не знаю, сработает ли это на третьей версии, но на 2009ой такое выражение работает:
Код:
for(i=0;i<70;i++)
{
       ttsbegin;
       while select forupdate table1
       where (table1.recid mod 70)==i
       {
              ....
              table1.update();

       } 

       ttscommit;

}
Поскольку на больших объемах данных, recid распределены достаточно равномерно, можно поделить объем на 70 почти одинаковых кусков.
Старый 06.04.2011, 02:05   #5  
Hyper is offline
Hyper
Участник
Соотечественники
 
163 / 29 (1) +++
Регистрация: 09.10.2003
Цитата:
Сообщение от fed Посмотреть сообщение
Не знаю, сработает ли это на третьей версии, но на 2009ой такое выражение работает
Спасибо за оригинальную идею, но в данном примере 70 раз производится выборка по RecId, так что при отсутствии индекса по RecId экспериментировать, пожалуй, не имеет смысла?
Старый 05.04.2011, 22:24   #6  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Hyper Посмотреть сообщение
Но мне почему-то казалось, что групповое обновление записей (скажем, 500 или 1000 в одной транзакции) на больших объемах даст ощутимый прирост производительности. Я не прав?
Не-а. Вернее, в большинстве случаев не прав.

В зависимости от версии SQL, от выставленного Recovery Model и от размера файла для логов.

Цитата:
Сообщение от Hyper Посмотреть сообщение
700 000 записей в одной транзакции? Причем там не одна такая таблица.
легко. для SQL - это не страшные объемы.

Цитата:
Сообщение от Hyper Посмотреть сообщение
Вроде бы чем больше измененных записей в одной транзакции, тем хуже Аксапта(/SQL?) справляется, причем при достижении определенного порога все еле ворочается?
Причем здесь Аксапта?

Цитата:
Сообщение от Hyper Посмотреть сообщение
Оптимальным решением было бы разбить таблицу на, скажем, 70 кусков, т.е. изменить все записи за 70 транзакций.
Ерунда это и онанизм какой-то.


возвращаемся к параметрам.
1.
Если у вас SQL2000, то там есть блокировка на чтение. (или более старший SQL, но у вас установлен режим совместимости с SQL2000). только тогда имеет смысл заниматься "разбиением на, скажем, 70 кусков"

Если же у вас более новый SQL, то заниматься ерундой не стоит.

2.
Если у вас Recovery Model = Full, то на сколько бы кусков вы ни разбивали, все будет записываться в Transaction log.
Если у вас Recovery Model = Simple, то вы выигрываете только на том, что каждая транзакция сразу очищается И файл транзакций НЕ растет.

3.
вот и приходим к размеру лога.
как вы изящно выразились "при достижении определенного порога все еле ворочается". просто транзакция заполняет весь лог, и СКЛ начинает увеличивать файл лога. на увеличение файла тратит значительное время.

в SQL Management Studio вы можете посмотреть отчет (по-моему, Disk Usage) и ужаснуться сколько времени SQL тратит на увеличение размера.

кроме того, исходя из своего опыта рискну предположить, что у вас таки SQL2005 или выше и параметры для файлов выставлены по-умолчанию. Дело в том, что начиная с SQL2005 файл Transaction Log по умолчанию растет по 1Мб (один мегабайт! - это ужасный параметр по умолчанию)

===============
следовательно, перестаньте заниматься фигней.
700тыс записей - смешной объем как для Аксапты, так и для СКЛ.

посмотрите в параметры СКЛ.
прежде всего увеличьте минимальный размер Transaction Log до вменяемого значения (поставьте гиг 5)
обязательно установите вменяемый размер прироста в фиксированных единицах (например, по 200-300Мб). Ни в коем случае не оставляйте по 1Мб. Так вы сократите фрагментацию как диска, так и внутреннюю SQL. Так вы минимизируете накладные расходы времени на рост Transaction Log.

И не парьтесь "кусками".
Сделайте или в одной нормальной транзакции. Или сделайте транзакцию на каждую запись.
Разница только логическая - если прервете обработку, то либо отменятся все изменения, либо останется то, что сделано.
__________________
полезное на axForum, github, vk, coub.
За это сообщение автора поблагодарили: Hyper (1), sukhanchik (2), Poleax (1).
Теги
axapta

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
вывод количества записей в таблице на web форме и указание текущей страницы таблицы bambuk1960 DAX: Программирование 1 06.07.2006 13:27
Axapta SP4 EE FP1 и Axapta SP4 EE polygris DAX: Администрирование 9 27.01.2006 11:27
Axapta 3.0 SP4 - нет русского языка Grimly DAX: Администрирование 3 06.12.2005 12:53
Установка Axapta 3.0 SP4 Easten Europe Alexander A. DAX: Администрирование 0 23.08.2005 15:24
Введение в Аксапту Роман Кошелев DAX: Прочие вопросы 0 18.12.2001 14:00

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

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

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