v8: Текст запроса SQL: быстрое удаление объектов #455245


#0 by ottto
Потребовалась быстрая удалялка объектов (объектов может удалятся более 10^7). Объекты: справочники, документы. Естественно в более - менее адекватное время эта задача решается если удалять средствами SQL. Пока задачу решал тупо выполнением через АДО текста SQL-запроса типа  "DELETE FROM .. WHERE _IDRRef IN (<список гуидов>) " уперся в ограничение что список определяемый конструкцией (v1,v2.....) по размерности не должен превышать 30000. Ну и собственно такая конструкция работает достаточно долго. Хочется поместить все гуиды во временную таблицу, а затем грохать (поскольку чистить нужно не одну таблицу, а таблицу изменений, таблицы табличных частей и т.д.). Собственно для большей части можно свести задачу к тому, что список удаляемых объектов можно определить результатом 1с-кого запроса. Идея писать конвектор 1с-кого в sql запрос меня не очень прельщает. (определение имен полей и передача параметров в списке - много кода) Есть две идее: 1. 1С -ким запросом получить ссылки поместить в запросе во временную таблицу. Обратится SQL- запросом к сгенерированной временной таблице 2. Создать 1с-кий запрос. определить как он транслируется в SQL. заменить SELECT на DELETE :) Собственно вопросы: как бы определить в какой запрос конвертнулся 1с-кий (программно) как определить имя созданной 1с-ким запросом временной таблицы.
#1 by H A D G E H O G s
MS SQL PROFILER
#2 by los_hooliganos
как определить имя созданной 1с-ким запросом временной таблицы. - если скуль 2005ый, то заипешься с этим. хотя нарабки есть)))
#3 by Ненавижу 1С
некоторые 1С-овские запросы реализуется несколькими SQL-запросами
#4 by los_hooliganos
простой селект напрямую транслируется.
#5 by Ненавижу 1С
ну самый простой да, но уже с использованием иерархии нет
#6 by H A D G E H O G s
НЕВЗЛЕТИТ
#7 by H A D G E H O G s
Не туда
#8 by H A D G E H O G s
Для примера: INSERT INTO #tt1 (_Q_000_F_000RRef) SELECT _Document45_Q_000_T_001._IDRRef AS _Q_000_F_000RRef FROM _Document45 _Document45_Q_000_T_001 WITH(NOLOCK)
#9 by H A D G E H O G s
#tt1 а не ##tt1
#10 by Господин ПЖ
truncate table
#11 by los_hooliganos
Автор погугли - Enterprise Integrator тамма даже видео трассировки есть из 1с.
#12 by los_hooliganos
непонял??
#13 by H A D G E H O G s
Даже если узнаешь имя ВТ (из профайлера) - ничего с ней не сделаешь (хм.., может ADO только подцепить), так как 1С оперирует локальными ВТ, а не глобальными
#14 by H A D G E H O G s
Нет, коннект ADO будет считаться уже другим сеансом скорее всего
#15 by los_hooliganos
ну дык надо из под одного сеанса узнавать.
#16 by Sadovnikov
Точно другим.
#17 by los_hooliganos
Короче говорю что заипется, но выход найти можно ;))
#18 by ottto
запуск удаления может производится не обязательно на сервере БД. Потребуется профайлер ставит на клиента, права altertrace и т.д. хочется через адо. скуль - да 5-й. какие наработки? Думал над этим но думаю всегда можно сделать последний запрос - простеньким) ... не понял:) откуда такая уверенность:)
#19 by los_hooliganos
к локальной временной таблице можно обратиться и из другого сеанса, но надо знать её полное имя.
#20 by ottto
смотрел - автор пароль наложил:) - уважаю чужой труд - взламывать не буду
#21 by ottto
да кстати... пипец
#22 by H A D G E H O G s
Нука, подробнее
#23 by los_hooliganos
а ты её глобальной сделай что мешает?))
#24 by H A D G E H O G s
Тупо: 1) Создать справочник, туда залить в 1С ке все удаляемые ссылки В SQL- фильтр при удалении по этому справочнику. Потом его DROPнуть
#25 by H A D G E H O G s
Читай условие задачи
#26 by los_hooliganos
см
#27 by H A D G E H O G s
см
#28 by los_hooliganos
кстати интересный вариант!
#29 by ottto
проблема в том что лимон записей хочется делить хотябы минуты 2. а так ну его)
#30 by ottto
тое есть генерить его часа 3 буду
#31 by ottto
+ не хочется типовую менять)
#32 by los_hooliganos
ну а если свою таблицу запросом сделать?
#33 by ottto
Кстати с регистром сведений может получится - он шустрее пишется и удаляется даже средствами 1с быстро. как?
#34 by los_hooliganos
те берешь селект запрос транслированный, и им через адо сам заливаешь в свою собственную таблицу.
#35 by ottto
я в sql не бум-бум
#36 by H A D G E H O G s
Как ты отделяешь "агнцев от козлищь" ?
#37 by H A D G E H O G s
Сидите уж. Я сам открою...
#38 by los_hooliganos
ну если восмерочный язык запросов знаешь то раберешься))
#39 by ottto
вопрос и был в том как получить транслированный запрос:)
#40 by H A D G E H O G s
MS SQL PROFILER
#41 by Sadovnikov
Шутник...
#42 by ottto
это не разово нужно сделать. процедурка должна быть. Вместо метода УдалитьОбъекты будет вывзываться
#43 by los_hooliganos
Кстати профайлер можно настроить на запись трассировки во временный текстовый файл, а 1с-ком запросе написать уникальный ключ. Время от времени парсишь файл профайлера, берешь запрос и вперед.))
#44 by H A D G E H O G s
Интересно вот, а 1С овцы используют локальные ВТ вместо глобальных чтобы не заморачиваться с коллизиями при многопользовательских подключениях? Так ведь сеанс Сервера Приложений - один. Не пойму...
#45 by los_hooliganos
Почему? СКЛ - очень простой язык.)) См в карточке достижения.))
#46 by H A D G E H O G s
Писать аналог УдалитьОбъекты да еще с контролем ссылочной целостности на SQL - нереально! Поэтому - в 1С ->РегСведений-> из него уже удаляем...
#47 by los_hooliganos
А почему локальные переменные лучше глобальных?
#48 by Sadovnikov
Я лучше на фотографию посмотрю :)
#49 by los_hooliganos
Сразу писали бы все нужные переменные в глобальнике и не парились бы))
#50 by los_hooliganos
Конфигурация то одна))
#51 by ottto
Контроль ссылочности никто не требовал. -удаляемые этой процедуры и справочники на момент удаления будут проверены средствами 1с. Нужно просто грохнуть массив ссылок.
#52 by H A D G E H O G s
Вот и я непонимаю. Давай у спросим?
#53 by los_hooliganos
Он щас скажет: Потому что восьмерка фуфло!
#54 by Sadovnikov
Чего именно спросим? :) Ты знал!!!
#55 by H A D G E H O G s
З.Ы. А РС лучше чем справочник - так как 1) Нет 3-х индексов по умолчанию присутствующих у справочника 2) Нет контроля уникальности кода 3) Нет генерации ГУИДа
#56 by los_hooliganos
Вообщем вопрос из разряда: Почему нельзя писать SELECT * FROM... в рабочих базах.
#57 by H A D G E H O G s
Почему 1С использует локальные а не глобальные ВТ?
#58 by Fester Adams
Непонятно?
#59 by H A D G E H O G s
Поясни
#60 by los_hooliganos
а приколись 2 8ные базы на одном сервере. и обе создали временные таблицы и...
#61 by Fester Adams
Для того что бы не парится с уникальностью имен таблиц.
#62 by H A D G E H O G s
Блиииин, вот я дятелъ. Слона не заметил. :-)
#63 by Sadovnikov
Вот хоть тресни - не помню, как 1С временные таблицы обзывает - GUID или нет?
#64 by ottto
я так понимаю сейчас больше всего людей интересует почему локальные, а неглобальные. Я воспринимаю такое положение как данность:). Задачу мне нужно решить в таких ограничениях, а решать ее в предположениях вот если бы были глобальными - не носит прикладной характер
#65 by Fester Adams
Вообще, если допустим число удаляемых записей из таблицы намного больше оставляемых, то проще выполнить truncate + insert оставляемых. При операции DELETE лучше использовать INNER JOIN -  тогда не надо заморачиваться с ограничениями IN
#66 by los_hooliganos
просто #tt1, #tt2 и тд
#67 by Fester Adams
Имя+номер сеанса
#68 by ottto
нет удаляем порядка ^6-^7 остается еще порядка ^7
#69 by rsv
Поместите интрересующие вас ссылки в физическую таблицу. И потом delete from ОткудаУдаляем where Поле IN (select Поле from ВашаТаблица).
#70 by H A D G E H O G s
Случаем не надо удалить все помеченные на удаление, без контроля ссылочной целостности?
#71 by Fester Adams
Это так, для инфо.
#72 by Sadovnikov
, Жэсть...
#73 by Fester Adams
Включи технологический журнал и посмотри.
#74 by H A D G E H O G s
Как это соотносится с #tt1, #tt2 ?
#75 by rsv
+ delete не быстр. Т.к. пишется инфа еще в лог транзакций. А у Truncate нет условия. Без транзакций но всю таблицу целиком. Так штааааа.
#76 by Fester Adams
Смотря о каких в/т идет речь, я про те, которые сама платформа генерит
#77 by H A D G E H O G s
Я про МенеджерВТ
#78 by ottto
нужно же еще поместить в физ таблицу - это тоже потеря времени. сейчас 1000000 элементов конструкцией DELETE FROM WHERE _IDRref in (v1,v2...) удаляются приблизительно 20 минут. Нужно бы сократить раз в 5 - 10
#79 by rsv
У вас не будт ограничений как в конструкции  IN ('','','','','',''..........)
#80 by los_hooliganos
Как увидеть реальное имя временной таблицы: where id = (select  object_id('tempdb..#tt1'))
#81 by ottto
Спасибо..., но как еще 1с-ку заставить выполнить такой код - поскольку нужно то именно из ее сеанса, а не АДО:)
#82 by H A D G E H O G s
Спасибо
#83 by PowerBoy
Все сделано до Вас:
#84 by ottto
...открыл смотрю. - вроде сам транслируешь в сиквел. Я побоялся с этим связываться:)
#85 by ottto
и почему-то условие по списку значений не работает.
#86 by PowerBoy
сделано на основе SQLPlus там есть свои ограничения
#87 by Axel2009
убить все индексы кроме кластерного и удалять. "Собственно для большей части можно свести задачу к тому, что список удаляемых объектов можно определить результатом 1с-кого запроса." нафига тогда во временную таблицу помещать? пищите сразу delete с запросом. если скуль 2005, то там можно delete top 10000 from bla-bla-bla
#88 by Axel2009
обращаться к локальным временным таблицам из другого сеанса нельзя.
#89 by Axel2009
преобразовать к виду delete from ОткудаУдаляем inner join (select Поле from ВашаТаблица) on IN поле = поле.
#90 by ottto
посмотрел транслятор. Не работает когда разыменовываешь более чем на одно поле. Например: Запрос: ВЫБРАТЬ    Номенклатура.Ссылка ИЗ    Справочник.Номенклатура КАК Номенклатура Транслируется в: Select     Nomenklatura._IDRRef From     _Reference30 As Nomenklatura А так удаление 1000000 заняло 5 минут. - приемлимый результат.
#91 by Axel2009
запусти технологический журнал и будет тебе щастье. там каждый запрос 1сный записывается в файл и какой из него получается скульный.
#92 by Axel2009
и с каких это пор можно к локальной временной таблице одного сеанса, обратиться из другого?
#93 by ottto
проблема в том что временной таблицы нет. ее нужно генерировать запросами - а как менее накладно ее сгенерировать это для меня БОЛЬШОЙ вопрос. мне нужен не разовый запрос... а процедурка УдалитьМногоОбъектов заменитель метода УдалитьОбъекты.
#94 by Axel2009
1. менее накладно ее не генерировать. а удалять порциями. 2. разово ты узнаешь откуда все удаляется. а потом уже этот запрос тянуть в продолжение.
#95 by ottto
ну вот не совсем так. В обработке насколько я понял получается временная таблица и потом данные херятся по конструкцией delete from ... where _iddref in (select _iddref from #table1) результат 3-5 минут если херить порционно: 333 раз по delete from ... where _iddref in (v1,...v30000) то 20 минут. (больше 30000 размер списка сделать нельзя - оптимизатор просит упростить запрос)
#96 by Axel2009
а IN использовать нельзя. потому как индексы не используются. нужно как в
#97 by ottto
Смотрю план запроса вроде впорядке все Cluster Index Seek выполняется ровно 1 раз на 30000 порцию.
#98 by Axel2009
delete top 3000 from ОткудаУдаляем t1 inner join (select _iddref from #table1) t2 on IN t1._iddref = t2._iddref только на таблицу #table1 навесить индекс по полю _iddref
#99 by Axel2009
а как его съедает оптимизатор? вызов на каждую строку @p1 or @p2 or @p3 и т.д. 30000 раз, и вызов на каждую строку.
Тэги:
Ответить:
Комментарии доступны только авторизированным пользователям

В этой группе 1С