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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 28.01.2018, 21:33   #1  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
495 / 232 (8) ++++++
Регистрация: 27.04.2006
Адрес: Montreal
быстрое удаление товаров
коллеги, может кто-нибудь поделиться кодом или ссылкой на таковой для быстрого удаления товаров InventTable, EcoResProduct и прочих связанных с ними таблиц?

нужно удалить примерно 122 тыщи позиций, так что желательно, чтоб запустить в батче в несколько потоков - есть 4 сервера с 4 ядрами.

спасибо!
__________________
Felix nihil admirari
-----------------------------------------------------------------------------------------------
AX2012
Старый 29.01.2018, 08:57   #2  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,082 / 1805 (67) ++++++++
Регистрация: 12.10.2004
Зачем быстро? Спешка нужна при ловле блох.
Лучше скрыть неиспользуемые позиции, а затем не спеша удалять.
Нужно ведь еще проверить что они нигде не используются.
Старый 29.01.2018, 09:08   #3  
KiselevSA is offline
KiselevSA
Злыдни
Аватар для KiselevSA
Злыдни
Лучший по профессии 2015
 
930 / 317 (12) ++++++
Регистрация: 25.01.2002
Адрес: Москва
Готового нет. Но вот так,вроде, должно сработать:

X++:
InventTable		_inventTable;
EcoResProduct	_ecoResProduct;
ItemId			_itemId;
RefRecId		_recId;

while select forupdate _inventTable
{
	_itemId = _inventTable.ItemId;
	_recId = _inventTable.Product;
	if(_inventTable.validateDelete())
	{
		ttsbegin;
		_inventTable.delete();
		ttscommit;
	}
	else
	{
		info(strfmt("Error delete item %1", _inventTable.ItemId));
	}
	
	while select forupdate _ecoResProduct
	where
		_ecoResProduct.RecId == _recId
		{
			if( _ecoResProduct.validateDelete())
			{
				ttsbegin;
				_ecoResProduct.delete();
				ttscommit;
			}
			else
			{
				info(strfmt("Error delete product %1", _ecoResProduct.DisplayProductNumber));
			}
		}
}
__________________
люди...считают, что если техника не ломается, то ее не нужно ремонтировать. Инженеры считают, что если она не ломается, то нуждается в совершенствовании.
Старый 29.01.2018, 11:57   #4  
БАХ43 is offline
БАХ43
Участник
 
34 / 33 (2) +++
Регистрация: 15.02.2013
Адрес: г.Москва, г. Зеленоград
А проводки по этим позициям есть? Если нет, то так быстрее будет. Еще можно на SQL запросе - еще быстрее получится.
X++:
ttsbegin;
    inventTable.skipDatabaseLog(true);
    inventTable.skipDataMethods(true);
    inventTable.skipDeleteActions(true);
    delete_from inventTable
        notexists join inventTrans
            where  inventTable.ItemId   == inventTrans.ItemId;

    ttscommit;
Старый 29.01.2018, 12:02   #5  
БАХ43 is offline
БАХ43
Участник
 
34 / 33 (2) +++
Регистрация: 15.02.2013
Адрес: г.Москва, г. Зеленоград
Еще в 5.0 есть класс InventUnusedDimCleanUp. Можно взять за основу, только поменять везде InventDim на InventTable. Там как раз пример построения запроса на SQL.
Старый 29.01.2018, 19:32   #6  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
495 / 232 (8) ++++++
Регистрация: 27.04.2006
Адрес: Montreal
Цитата:
Сообщение от KiselevSA Посмотреть сообщение
Готового нет. Но вот так,вроде, должно сработать:
таким вот сейчас и пользуюсь, но нужна обёртка для параллельной обработки
__________________
Felix nihil admirari
-----------------------------------------------------------------------------------------------
AX2012
Старый 29.01.2018, 19:34   #7  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
495 / 232 (8) ++++++
Регистрация: 27.04.2006
Адрес: Montreal
@Модератор, а где кнопка "Мне не нравится"? ещё лучше бы "Удалить камент как бестолковый"
__________________
Felix nihil admirari
-----------------------------------------------------------------------------------------------
AX2012
Старый 29.01.2018, 20:19   #8  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
495 / 232 (8) ++++++
Регистрация: 27.04.2006
Адрес: Montreal
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
А "в лоб" - нельзя?

Отдельную таблицу со списком удаляемой номенклатуры и RunBaseBatch с возможностью указать диапазон по этой таблице. Далее несколько пакетных заданий по разным диапазонам. Заодно и лог удаления останется
именно это и надо! где взять?
__________________
Felix nihil admirari
-----------------------------------------------------------------------------------------------
AX2012
Старый 29.01.2018, 20:29   #9  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,400 / 885 (32) +++++++
Регистрация: 13.01.2004
Цитата:
Сообщение от wojzeh Посмотреть сообщение
именно это и надо! где взять?
В смысле? Создать. Чего сложного-то? Как-то ведь 122 тысячи позиций указываете. Неужели константами в джобе? Ну, так вместо констант создать табличку и в нее загнать все 122 тысячи значений
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
Старый 29.01.2018, 20:33   #10  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,400 / 885 (32) +++++++
Регистрация: 13.01.2004
Как вариант, можно привязать удаляемые номенклатуры как каким-нибудь особым веткам классификатора. И отдельные пакетники каждый по своей ветке
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
Старый 29.01.2018, 20:39   #11  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
495 / 232 (8) ++++++
Регистрация: 27.04.2006
Адрес: Montreal
в исходном топике не было вопроса "как?", там была просьба поделиться готовым кодом.

Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
В смысле? Создать. Чего сложного-то?
сложного то, что времени нет
__________________
Felix nihil admirari
-----------------------------------------------------------------------------------------------
AX2012
Старый 30.01.2018, 00:03   #12  
БАХ43 is offline
БАХ43
Участник
 
34 / 33 (2) +++
Регистрация: 15.02.2013
Адрес: г.Москва, г. Зеленоград
Создать таблицу со списком удаляемых позиций, например InventTableCleanUp, дальше примерно так:
X++:
        InventTable.skipDataMethods(true);
        InventTable.skipDeleteActions(true);
        InventTable.skipDatabaseLog(true);
        InventTable.skipEvents(true);

        delete_from InventTable 
            exists join InventTableCleanUp
            where InventTableCleanUp.ItemId == InventTable.ItemId ;
у меня 9 млн записей в InventDim за 3 часа удалилось. на 122 тыс - считайте сами. Там просто к InventTable еще куча таблиц привязана, которые тоже надо очистить. Но, я думаю, что удалять номенклатуры, по которым есть проводки - это полный пипец. А как же остатки? Вдруг не все в ноль. Тогда надо и InventTrans чистить и InventSum.
Старый 30.01.2018, 00:42   #13  
БАХ43 is offline
БАХ43
Участник
 
34 / 33 (2) +++
Регистрация: 15.02.2013
Адрес: г.Москва, г. Зеленоград
Может есть еще какой-то критерий, по которому можно отсортировать записи? Например, я удалял данные из неактуальных компаний (наследие предков) таким вот кодом
X++:
protected void deleteAllNotCurCompany()
{
    str                             sqlStr;
    Dictionary                      dict = new Dictionary();
    SysDictTable                    dictTable;
    tableId                         tableId;
    int64                           recordCount, recordSum, tableCount;
    Common                          common;
    Connection                      connection = new Connection();
    SqlSystem                       sqlSystem = new SqlSystem();
    Statement                       statement;
    int                             i;
;

    
    progressBar.setText(strfmt("Удаляю таблицы неактуальных компаний (%1) ...", dict.tableCnt()));
    progressBar.setTotal(dict.tableCnt(), 2);
    
    for (i=1; i<=dict.tableCnt(); i++)
    {
        progressBar.incCount(1, 2);
        tableId = dict.tableCnt2Id(i);
        dictTable = new SysDictTable(tableId);
        if (!dictTable || dictTable.isMap() || dictTable.isTmp() || dictTable.isView() || !dictTable.dataPrCompany())
            continue;
        common = dictTable.makeRecord();
        common.disableCache(true);

        while select crosscompany count(RecId) from common
            group by dataAreaId
        {
            recordCount = common.RecId;
            if (recordCount && !this.isInCurCompany(common.dataAreaId))
            {
                sqlStr  = 'DELETE FROM ' + dictTable.name(DbBackend::Sql); 
                sqlStr += ' WHERE (' + dictTable.fieldName(fieldnum(common, DataAreaId),DbBackend::Sql);
                sqlStr += ' = ' + sqlSystem.sqlLiteral(common.dataAreaId) + ') ';
                connection.ttsbegin();
                statement = connection.createStatement();
                new SqlStatementExecutePermission(sqlStr).assert();
                statement.executeUpdate(sqlStr);
                connection.ttscommit();
                CodeAccessPermission::revertAssert();
                recordSum += recordCount;
                tableCount++;
            }
        }
    }
    info(strfmt("Удалено %1 записей в %2 таблицах неактуальных компаний", recordSum, tableCount));
}
X++:
//BAH Да, если компания текущая или виртуальная в текущей
private boolean isInCurCompany(DataAreaId _dataAreaId)
{
;

    if (this.getCompanyFromVirtual(_dataAreaId) == curExt())
        return true;
    return false;
}
X++:
//BAH186 26.01.2018 Возвращает первую попавшуюся компанию, входящую в состав виртуальной 
private DataAreaId getCompanyFromVirtual(DataAreaId _virtual)
{
    VirtualDataAreaList virtualDataAreaList;
    ;
    if (this.isVirtual(_virtual))
    {
        select firstonly virtualDataAreaList
            where virtualDataAreaList.virtualDataArea == _virtual;
        return virtualDataAreaList.Id ? virtualDataAreaList.Id : "";
    }
    else
        return _virtual;
}
X++:
//BAH186 Да, если компания виртуальная
private boolean isVirtual(DataAreaId _dataAreaId)
{
    DataArea dataArea;
    boolean  ret;
    ;
    select firstonly id from dataArea
        where dataArea.id == _dataAreaId &&
              dataArea.isVirtual == NoYes::Yes;
    if (dataArea)
    {
        ret = true;
    }
    return ret;
}
почти 20 млн записей (Удалено 19772500 записей в 403 таблицах неактуальных компаний
) за 1-2 часа (точнее не засекал, отслеживал каждый шаг в дебаггере). И то на тестовой базе, которая в 3-5 раз медленнее рабочей.
__________________
Я прибыл к вам из Кантемировской дивизии. А там, как известно, дураков не держат!
Старый 02.02.2018, 18:59   #14  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
495 / 232 (8) ++++++
Регистрация: 27.04.2006
Адрес: Montreal
вот решение http://alexvoy.blogspot.ca/2018/02/p...dating-or.html
__________________
Felix nihil admirari
-----------------------------------------------------------------------------------------------
AX2012
За это сообщение автора поблагодарили: Logger (3), Vadik (1).
Теги
batch, inventtable, multithreading, полезное, удаление

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Отображение распаковки, запаковки и переупаковки товаров Bar DAX: Функционал 9 03.10.2011 17:41
Удаление товаров korolf DAX: Программирование 4 27.11.2002 15:02
Группы товаров. max99 DAX: Функционал 4 22.10.2002 18:10
Удаление проекта Maxim Gorbunov DAX: Программирование 0 24.12.2001 23:04
Опции темы Поиск в этой теме
Поиск в этой теме:

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

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

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

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 12:41.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.