Имя: Пароль:
1C
 
v8: Текст запроса SQL: быстрое удаление объектов
0 ottto
 
15.01.10
11:45
Потребовалась быстрая удалялка объектов (объектов может удалятся более 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 H A D G E H O G s
 
15.01.10
11:49
MS SQL PROFILER
2 los_hooliganos
 
15.01.10
11:50
как определить имя созданной 1с-ким запросом временной таблицы.
- если скуль 2005ый, то заипешься с этим. хотя нарабки есть)))
3 Ненавижу 1С
 
гуру
15.01.10
11:51
некоторые 1С-овские запросы реализуется несколькими SQL-запросами
4 los_hooliganos
 
15.01.10
11:52
(3) простой селект напрямую транслируется.
5 Ненавижу 1С
 
гуру
15.01.10
11:53
(4) ну самый простой да, но уже с использованием иерархии нет
6 H A D G E H O G s
 
15.01.10
11:54
НЕВЗЛЕТИТ
7 H A D G E H O G s
 
15.01.10
11:54
(2) Не туда
8 H A D G E H O G s
 
15.01.10
11:54
http://www.cyberguru.ru/database/sqlserver/temp-tables.html


Для примера:

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 H A D G E H O G s
 
15.01.10
11:54
#tt1 а не ##tt1
10 Господин ПЖ
 
15.01.10
11:55
truncate table
11 los_hooliganos
 
15.01.10
11:55
Автор погугли - Enterprise Integrator
тамма даже видео трассировки есть из 1с.
12 los_hooliganos
 
15.01.10
11:56
(7) непонял??
13 H A D G E H O G s
 
15.01.10
11:57
(12) Даже если узнаешь имя ВТ (из профайлера) - ничего с ней не сделаешь (хм.., может ADO только подцепить), так как 1С оперирует локальными ВТ, а не глобальными
14 H A D G E H O G s
 
15.01.10
11:58
Нет, коннект ADO будет считаться уже другим сеансом скорее всего
15 los_hooliganos
 
15.01.10
11:58
(13) ну дык надо из под одного сеанса узнавать.
16 Sadovnikov
 
15.01.10
11:58
(14) Точно другим.
17 los_hooliganos
 
15.01.10
11:59
Короче говорю что заипется, но выход найти можно ;))
18 ottto
 
15.01.10
11:59
(1) запуск удаления может производится не обязательно на сервере БД. Потребуется профайлер ставит на клиента, права altertrace и т.д. хочется через адо.
(2) скуль - да 5-й. какие наработки?
(3) Думал над этим но думаю всегда можно сделать последний запрос - простеньким)
(6) ... не понял:) откуда такая уверенность:)
19 los_hooliganos
 
15.01.10
12:00
к локальной временной таблице можно обратиться и из другого сеанса, но надо знать её полное имя.
20 ottto
 
15.01.10
12:02
(11) смотрел - автор пароль наложил:) - уважаю чужой труд - взламывать не буду
21 ottto
 
15.01.10
12:03
(13) да кстати...
пипец
22 H A D G E H O G s
 
15.01.10
12:03
(19) Нука, подробнее
23 los_hooliganos
 
15.01.10
12:04
(21) а ты её глобальной сделай
что мешает?))
24 H A D G E H O G s
 
15.01.10
12:05
(21) Тупо:

1) Создать справочник, туда залить в 1С ке все удаляемые ссылки

В SQL- фильтр при удалении по этому справочнику.

Потом его DROPнуть
25 H A D G E H O G s
 
15.01.10
12:05
(23) Читай условие задачи
26 los_hooliganos
 
15.01.10
12:05
(22) см (23)
27 H A D G E H O G s
 
15.01.10
12:05
(26) см (25)
28 los_hooliganos
 
15.01.10
12:06
(24) кстати интересный вариант!
29 ottto
 
15.01.10
12:06
(24) проблема в том что лимон записей хочется делить хотябы минуты 2.
а так ну его)
30 ottto
 
15.01.10
12:06
тое есть генерить его часа 3 буду
31 ottto
 
15.01.10
12:07
+ не хочется типовую менять)
32 los_hooliganos
 
15.01.10
12:07
ну а если свою таблицу запросом сделать?
33 ottto
 
15.01.10
12:08
Кстати с регистром сведений может получится - он шустрее пишется и удаляется даже средствами 1с быстро.
(32) как?
34 los_hooliganos
 
15.01.10
12:08
те берешь селект запрос транслированный, и им через адо сам заливаешь в свою собственную таблицу.
35 ottto
 
15.01.10
12:08
я в sql не бум-бум
36 H A D G E H O G s
 
15.01.10
12:08
(0) Как ты отделяешь "агнцев от козлищь" ?
37 H A D G E H O G s
 
15.01.10
12:09
(35) Сидите уж. Я сам открою...
38 los_hooliganos
 
15.01.10
12:09
(35)ну если восмерочный язык запросов знаешь то раберешься))
39 ottto
 
15.01.10
12:11
(34) вопрос и был в том как получить транслированный запрос:)
40 H A D G E H O G s
 
15.01.10
12:11
(39) MS SQL PROFILER
41 Sadovnikov
 
15.01.10
12:12
(38) Шутник...
42 ottto
 
15.01.10
12:12
это не разово нужно сделать. процедурка должна быть.
Вместо метода УдалитьОбъекты() будет вывзываться
43 los_hooliganos
 
15.01.10
12:13
Кстати профайлер можно настроить на запись трассировки во временный текстовый файл, а 1с-ком запросе написать уникальный ключ.
Время от времени парсишь файл профайлера, берешь запрос и вперед.))
44 H A D G E H O G s
 
15.01.10
12:13
Интересно вот, а 1С овцы используют локальные ВТ вместо глобальных чтобы не заморачиваться с коллизиями при многопользовательских подключениях? Так ведь сеанс Сервера Приложений - один. Не пойму...
45 los_hooliganos
 
15.01.10
12:14
(41) Почему? СКЛ - очень простой язык.))
См в карточке достижения.))
46 H A D G E H O G s
 
15.01.10
12:15
Писать аналог УдалитьОбъекты() да еще с контролем ссылочной целостности на SQL - нереально! Поэтому - в 1С ->РегСведений-> из него уже удаляем...
47 los_hooliganos
 
15.01.10
12:16
(44) А почему локальные переменные лучше глобальных?
48 Sadovnikov
 
15.01.10
12:16
(45) Я лучше на фотографию посмотрю :)
49 los_hooliganos
 
15.01.10
12:16
Сразу писали бы все нужные переменные в глобальнике и не парились бы))
50 los_hooliganos
 
15.01.10
12:17
Конфигурация то одна))
51 ottto
 
15.01.10
12:17
(46) Контроль ссылочности никто не требовал. -удаляемые этой процедуры и справочники на момент удаления будут проверены средствами 1с. Нужно просто грохнуть массив ссылок.
52 H A D G E H O G s
 
15.01.10
12:18
(49) Вот и я непонимаю. Давай у Sadovnikov спросим?
53 los_hooliganos
 
15.01.10
12:19
(52) Он щас скажет: Потому что восьмерка фуфло!
54 Sadovnikov
 
15.01.10
12:20
(52) Чего именно спросим? :)
(53) Ты знал!!!
55 H A D G E H O G s
 
15.01.10
12:21
З.Ы. А РС лучше чем справочник - так как
1) Нет 3-х индексов по умолчанию присутствующих у справочника
2) Нет контроля уникальности кода
3) Нет генерации ГУИДа
56 los_hooliganos
 
15.01.10
12:21
Вообщем вопрос из разряда:
Почему нельзя писать SELECT * FROM...
в рабочих базах.
57 H A D G E H O G s
 
15.01.10
12:21
(54) Почему 1С использует локальные а не глобальные ВТ?
58 Fester Adams
 
15.01.10
12:22
(57) Непонятно?
59 H A D G E H O G s
 
15.01.10
12:23
(58) Поясни
60 los_hooliganos
 
15.01.10
12:23
(57) а приколись 2 8ные базы на одном сервере.
и обе создали временные таблицы и...
61 Fester Adams
 
15.01.10
12:23
(59) Для того что бы не парится с уникальностью имен таблиц.
62 H A D G E H O G s
 
15.01.10
12:25
(60) Блиииин, вот я дятелъ. Слона не заметил. :-)
63 Sadovnikov
 
15.01.10
12:25
(57) Вот хоть тресни - не помню, как 1С временные таблицы обзывает - GUID или нет?
64 ottto
 
15.01.10
12:26
я так понимаю сейчас больше всего людей интересует почему локальные, а неглобальные.
Я воспринимаю такое положение как данность:). Задачу мне нужно решить в таких ограничениях, а решать ее в предположениях вот если бы были глобальными - не носит прикладной характер
65 Fester Adams
 
15.01.10
12:26
Вообще, если допустим число удаляемых записей из таблицы намного больше оставляемых, то проще выполнить truncate + insert оставляемых.

При операции DELETE лучше использовать INNER JOIN -  тогда не надо заморачиваться с ограничениями IN
66 los_hooliganos
 
15.01.10
12:27
(63) просто #tt1, #tt2 и тд
67 Fester Adams
 
15.01.10
12:28
(63) Имя+номер сеанса
68 ottto
 
15.01.10
12:28
(65) нет удаляем порядка ^6-^7 остается еще порядка ^7
69 rsv
 
15.01.10
12:30
(0) Поместите интрересующие вас ссылки в физическую таблицу. И потом

delete from ОткудаУдаляем where Поле IN (select Поле from ВашаТаблица).
70 H A D G E H O G s
 
15.01.10
12:31
(68) Случаем не надо удалить все помеченные на удаление, без контроля ссылочной целостности?
71 Fester Adams
 
15.01.10
12:31
(68) Это так, для инфо.
72 Sadovnikov
 
15.01.10
12:31
(66), (67) Жэсть...
73 Fester Adams
 
15.01.10
12:32
(72) Включи технологический журнал и посмотри.
74 H A D G E H O G s
 
15.01.10
12:32
(67) Как это соотносится с
#tt1, #tt2 ?
75 rsv
 
15.01.10
12:33
+(69) delete не быстр. Т.к. пишется инфа еще в лог транзакций. А у Truncate нет условия. Без транзакций но всю таблицу целиком. Так штааааа.
76 Fester Adams
 
15.01.10
12:34
(74) Смотря о каких в/т идет речь, я про те, которые сама платформа генерит
77 H A D G E H O G s
 
15.01.10
12:34
(76) Я про МенеджерВТ
78 ottto
 
15.01.10
12:35
(69) нужно же еще поместить в физ таблицу - это тоже потеря времени.
сейчас 1000000 элементов конструкцией DELETE FROM WHERE _IDRref in (v1,v2...) удаляются приблизительно 20 минут. Нужно бы сократить раз в 5 - 10
79 rsv
 
15.01.10
12:36
(78) У вас не будт ограничений как в конструкции  IN ('','','','','',''..........)
80 los_hooliganos
 
15.01.10
12:37
Как увидеть реальное имя временной таблицы:

select name
from tempdb..sysobjects(nolock)
where id = (select  object_id('tempdb..#tt1'))
81 ottto
 
15.01.10
12:38
(80) Спасибо..., но как еще 1с-ку заставить выполнить такой код - поскольку нужно то именно из ее сеанса, а не АДО:)
82 H A D G E H O G s
 
15.01.10
12:41
(80) Спасибо
83 PowerBoy
 
15.01.10
12:42
Все сделано до Вас:

http://infostart.ru/public/16731/
84 ottto
 
15.01.10
12:45
...открыл смотрю. - вроде сам транслируешь в сиквел.
Я побоялся с этим связываться:)
85 ottto
 
15.01.10
12:47
и почему-то условие по списку значений не работает.
86 PowerBoy
 
15.01.10
12:50
(85) сделано на основе SQLPlus
http://www.infostart.ru/public/14692/

там есть свои ограничения
87 Axel2009
 
15.01.10
12:54
(0) убить все индексы кроме кластерного и удалять.
"Собственно для большей части можно свести задачу к тому, что список удаляемых объектов можно определить результатом 1с-кого запроса."
нафига тогда во временную таблицу помещать? пищите сразу delete с запросом. если скуль 2005, то там можно delete top 10000 from bla-bla-bla
88 Axel2009
 
15.01.10
13:01
(81) обращаться к локальным временным таблицам из другого сеанса нельзя.
89 Axel2009
 
15.01.10
13:02
(78) преобразовать к виду
delete from ОткудаУдаляем inner join (select Поле from ВашаТаблица) on IN поле = поле.
90 ottto
 
15.01.10
13:03
(86) посмотрел транслятор.
Не работает когда разыменовываешь более чем на одно поле. Например:
Запрос:

ВЫБРАТЬ
   Номенклатура.Ссылка
ИЗ
   Справочник.Номенклатура КАК Номенклатура
ГДЕ
   Номенклатура.Родитель.Код В ("1111", "222")

Транслируется в:


Select
    Nomenklatura._IDRRef
From
    _Reference30 As Nomenklatura
Where
    Nomenklatura.Roditelyy.Kod In ( '1111' , '222' )


Собственно глюк: Nomenklatura.Roditelyy.Kod

А так удаление 1000000 заняло 5 минут. - приемлимый результат.
91 Axel2009
 
15.01.10
13:06
(90) запусти технологический журнал и будет тебе щастье. там каждый запрос 1сный записывается в файл и какой из него получается скульный.
92 Axel2009
 
15.01.10
13:07
(19) и с каких это пор можно к локальной временной таблице одного сеанса, обратиться из другого?
93 ottto
 
15.01.10
13:08
(89) проблема в том что временной таблицы нет.
ее нужно генерировать запросами - а как менее накладно ее сгенерировать это для меня БОЛЬШОЙ вопрос.

(91) мне нужен не разовый запрос...
а процедурка УдалитьМногоОбъектов заменитель метода УдалитьОбъекты.
94 Axel2009
 
15.01.10
13:11
(93)
1. менее накладно ее не генерировать. а удалять порциями.
2. разово ты узнаешь откуда все удаляется. а потом уже этот запрос тянуть в продолжение.
95 ottto
 
15.01.10
13:25
(94) ну вот не совсем так.
В обработке (86) насколько я понял получается временная таблица и потом данные херятся по конструкцией delete from ... where _iddref in (select _iddref from #table1) результат 3-5 минут
если херить порционно:
333 раз по
delete from ... where _iddref in (v1,...v30000) то 20 минут.
(больше 30000 размер списка сделать нельзя - оптимизатор просит упростить запрос)
96 Axel2009
 
15.01.10
13:26
(95) а IN использовать нельзя. потому как индексы не используются. нужно как в (89)
97 ottto
 
15.01.10
13:30
Смотрю план запроса вроде впорядке все
Cluster Index Seek выполняется ровно 1 раз на 30000 порцию.
98 Axel2009
 
15.01.10
13:30
delete top 3000 from ОткудаУдаляем t1 inner join (select _iddref from #table1) t2 on IN t1._iddref = t2._iddref
только на таблицу #table1 навесить индекс по полю _iddref
99 Axel2009
 
15.01.10
13:31
а как его съедает оптимизатор?
вызов на каждую строку @p1 or @p2 or @p3 и т.д. 30000 раз, и вызов на каждую строку.
100 Aleksey_3
 
15.01.10
14:40
(100)
Независимо от того, куда вы едете — это в гору и против ветра!