|
v7: 1с++ ускорение Запрос.УложитьСписокОбъектов | ☑ | ||
---|---|---|---|---|
0
dk
21.01.19
✎
12:12
|
исходные:
1с++, SQL 2000 / 2008 Проблема: Довольно долго укладываются большие списке объектов (1000 элементов и больше) Без иерархии: 2430 мс С иерархией: 2394 мс ВыполнитьSQL_ИзТЗ: 229 мс Ниже замеры и код |
|||
1
dk
21.01.19
✎
12:13
|
|
|||
2
dk
21.01.19
✎
12:16
|
Собственно вопрос
кто-то занимался ускорением уложитьсписок объектов? либо есть универсальный запрос по получению иерархии шустрый? |
|||
3
trad
21.01.19
✎
12:19
|
а если так?
CREATE TABLE #Фильтр3 (Счет Char(9), PRIMARY KEY CLUSTERED (Счет)) |
|||
4
dk
21.01.19
✎
12:23
|
(3) пофигу
************************************** Без иерархии: 2370 Кол-во: 3000 С иерархией: 2590 Кол-во: 3000 ВыполнитьSQL_ИзТЗ: 221 Кол-во: 30 |
|||
5
dk
21.01.19
✎
12:23
|
Кол-во: 3000
|
|||
6
trad
21.01.19
✎
12:25
|
затестил у себя (на $Справочник.Номенклатура):
************************************** Без иерархии: 890 Кол-во: 3000 С иерархией: 1062 Кол-во: 3286 ВыполнитьSQL_ИзТЗ: 127 Кол-во: 3000 |
|||
7
dk
21.01.19
✎
12:26
|
ну гдето в 7-8 раз шустрее
|
|||
8
Туц
21.01.19
✎
12:27
|
Альтернатива это импорт из командной строки.
|
|||
9
Mikeware
21.01.19
✎
12:36
|
а нужен ли такой список? может, его сразу формировать во временной таблице запросом?
|
|||
10
Туц
21.01.19
✎
12:36
|
Кстати через adodb можно бинарник пихнуть ввиде xml
|
|||
11
dk
21.01.19
✎
12:38
|
(9) ну это например может быть какой-то охрененный список товаров из Excel загружен в несколько тыс строк или группа первого уровня
|
|||
12
Туц
21.01.19
✎
12:45
|
Ещё вариант. Укладывать не таблицу и список строк. Т.е. строку таблицы приводить суммировать в строку. Чисто в теории будет кратный количеству колонок выйгрышь
|
|||
13
Mikeware
21.01.19
✎
12:48
|
(11) так по идее по адо можно сразу из экселя...
а группу первого уровня можно запросом собрать |
|||
14
trad
21.01.19
✎
12:48
|
имхо, проблема в медленном итерировании списка внутрях УложитьСписокОбъектов
|
|||
15
Sserj
21.01.19
✎
12:48
|
(11) Если список товаров то ничего не сделаешь. А если группа первого уровня, да и вообще любая группа лучше сделать через CTE фильтр групп и условие по родителю.
|
|||
16
trad
21.01.19
✎
12:50
|
вердикт. сделать свой УложитьСписок на основе ВыполнитьSQL_ИзТЗ.
Разворот иерархии написать самому или спиимствовать у УложитьСписок |
|||
17
dk
21.01.19
✎
12:53
|
(15) sql 2000 не дружит с cte
(16) угу, смотрю профайлером как штатный робит и как выполнитьтз |
|||
18
Вафель
21.01.19
✎
12:55
|
а зачем нежен фильтр из 3000 элементов?
|
|||
19
Sserj
21.01.19
✎
12:56
|
(17) Ну там в топике 2008 было написано. Ради CTE да оконных функций можно было бы и поднапрячься с переходом на посвежее :)
|
|||
20
dk
21.01.19
✎
12:59
|
(18) см (11)
|
|||
21
Mikeware
21.01.19
✎
13:06
|
(16) другими словами, не использовать универсальный способ, на написать частный для частных случаев.
|
|||
22
trad
21.01.19
✎
13:08
|
(21) честно сказать, я удивлен, что неиерархический УложитьСписокОбъектов так проигрывает ВыполнитьSQL_ИзТЗ
|
|||
23
Mikeware
21.01.19
✎
13:15
|
(22) из-за универсальности. но да, проигрыш слишком велик...
|
|||
24
trad
21.01.19
✎
13:33
|
так дело в том, что УложитьСписок не имеет какой-то там универсальности.
То, что он умеет еще делать запрос по развороту иерархии, не влияет на само "укладывание" То, что в таблице есть еще служебное поле "isfolder", тоже не сказывается |
|||
25
Salimbek
21.01.19
✎
15:46
|
(24) Может кто допилит на использование Массив, Структура, Соответствие или чего еще быстрого (мечтательно) :-)
|
|||
26
ADirks
22.01.19
✎
08:50
|
(25) Нет смысла, т.к. накладные расходы на уровне СУБД на порядок (порядки?) больше, чем на исполнение кода 1С.
Самостоятельная реализация УложитьСписок() в данном случае полезна в исследовательских целях, а то действительно непонятно, откуда такие тайминги. |
|||
27
Дык ё
22.01.19
✎
09:12
|
(16) какое чудесное слово - "спиимствовать" :)
а включение режимrpc на тайминги уложитьсписок не влияет? |
|||
28
trad
22.01.19
✎
14:24
|
(27) режимrpc на уложитьсписок не влияет
|
|||
29
dk
25.01.19
✎
12:37
|
с прямым заполнением в скуле пока не прокатило
------------- сделал просто если в темп потом из темпа забираем тока группы эти группы штатно укладываем склеиваем оба списка ------------- Процедура Сформировать4() Запрос = СоздатьОбъект("ODBCRecordSet"); ВремТЗ = СоздатьОбъект("ТаблицаЗначений"); ВремТЗ.НоваяКолонка("Товар", "Справочник.Номенклатура"); //ВремТЗ.НоваяСтрока(); //ВремТЗ.Товар = ВыбНоменклатура; ТекстЗапроса = "SELECT TOP 1000 ID [Товар $Справочник.Номенклатура] FROM $Справочник.Номенклатура (NOLOCK) WHERE Id = :ВыбТовар--WHERE ISFOLDER = 2"; Запрос.УстановитьТекстовыйПараметр("ВыбТовар", ВыбНоменклатура); Запрос.ВыполнитьИнструкцию(ТекстЗапроса, ВремТЗ); СЗ_Фильтр = СоздатьОбъект("СписокЗначений"); ВремТЗ.Выгрузить(СЗ_Фильтр,,,"Товар"); Сообщить("**************************************"); Нач = _GetPerformanceCounter(); Запрос.УложитьСписокОбъектов(СЗ_Фильтр, "#Фильтр1"); Сообщить("Без иерархии: " + (_GetPerformanceCounter() - Нач)); Сообщить("Кол-во: " + Запрос.ВыполнитьСкалярный("SELECT COUNT(*) FROM #Фильтр1")); Нач = _GetPerformanceCounter(); Запрос.УложитьСписокОбъектов(СЗ_Фильтр, "#Фильтр2", "Номенклатура"); Сообщить("С иерархией: " + (_GetPerformanceCounter() - Нач)); Сообщить("Кол-во: " + Запрос.ВыполнитьСкалярный("SELECT COUNT(*) FROM #Фильтр2")); Нач = _GetPerformanceCounter(); ТекстЗапроса = " |IF OBJECT_ID(N'tempdb..#Фильтр3','U') IS NOT NULL DROP TABLE #Фильтр3 |; |CREATE TABLE #Фильтр3 (Товар Char(9), UNIQUE CLUSTERED (Товар)) |; |IF OBJECT_ID(N'tempdb..#Фильтр4','U') IS NOT NULL DROP TABLE #Фильтр4 |; |CREATE TABLE #Фильтр4 (Товар Char(9), UNIQUE CLUSTERED (Товар)) |; |IF OBJECT_ID(N'tempdb..#Фильтр6','U') IS NOT NULL DROP TABLE #Фильтр6 |; |CREATE TABLE #Фильтр6 (Товар Char(9), UNIQUE CLUSTERED (Товар))"; Запрос.ВыполнитьИнструкцию(ТекстЗапроса); Запрос.Подготовить("INSERT INTO #Фильтр3 VALUES(?)"); Запрос.ВыполнитьSQL_ИзТЗ(ВремТЗ); //Сообщить("ВыполнитьSQL_ИзТЗ: " + (_GetPerformanceCounter() - Нач)); //Сообщить("Кол-во ВыполнитьSQL_ИзТЗ: " + Запрос.ВыполнитьСкалярный("SELECT COUNT(*) FROM #Фильтр3")); ТекстЗапроса = " | INSERT INTO #Фильтр4 | SELECT Ном.ID Товар | FROM $Справочник.Номенклатура AS Ном With (NOLOCK) | INNER JOIN #Фильтр3 Ф0 (NOLOCK) ON (Ф0.Товар = Ном.ID) AND (Ном.ISFOLDER = 1) |"; Запрос.ВыполнитьИнструкцию(ТекстЗапроса); //Сообщить("Фильтр4: " + (_GetPerformanceCounter() - Нач)); //Сообщить("Кол-во Фильтр4: " + Запрос.ВыполнитьСкалярный("SELECT COUNT(*) FROM #Фильтр4")); ТекстЗапроса = " | SELECT Ф0.Товар [Товар $Справочник.Номенклатура] | FROM #Фильтр4 Ф0 (NOLOCK) |"; Врем2 = СоздатьОбъект("ТаблицаЗначений"); Запрос.ВыполнитьИнструкцию(ТекстЗапроса, Врем2); //Сообщить("Фильтр4_1: " + (_GetPerformanceCounter() - Нач)); //Сообщить("Кол-во Фильтр4_1: " + Врем2.КоличествоСтрок()); СЗ_Фильтр = СоздатьОбъект("СписокЗначений"); Врем2.Выгрузить(СЗ_Фильтр,,,"Товар"); Запрос.УложитьСписокОбъектов(СЗ_Фильтр, "#Фильтр5", "Номенклатура"); //Сообщить("Фильтр5: " + (_GetPerformanceCounter() - Нач)); //Сообщить("Кол-во Фильтр5: " + Запрос.ВыполнитьСкалярный("SELECT COUNT(*) FROM #Фильтр5")); ТекстЗапроса = " | INSERT INTO #Фильтр6 | SELECT Ф3.Товар FROM #Фильтр3 Ф3 (NOLOCK) | LEFT JOIN #Фильтр4 Ф4 (NOLOCK) ON Ф3.Товар = Ф4.Товар | WHERE Ф4.Товар IS NULL | | UNION-- ALL | | SELECT Val FROM #Фильтр5 (NOLOCK) | |"; Запрос.ВыполнитьИнструкцию(ТекстЗапроса); ТекстЗапроса = " |IF OBJECT_ID(N'tempdb..#Фильтр3','U') IS NOT NULL DROP TABLE #Фильтр3 |; |; |IF OBJECT_ID(N'tempdb..#Фильтр4','U') IS NOT NULL DROP TABLE #Фильтр4 |;"; Запрос.ВыполнитьИнструкцию(ТекстЗапроса); Сообщить("Фильтр6: " + (_GetPerformanceCounter() - Нач)); Сообщить("Кол-во Фильтр6: " + Запрос.ВыполнитьСкалярный("SELECT COUNT(*) FROM #Фильтр6")); КонецПроцедуры |
|||
30
dk
25.01.19
✎
12:38
|
замеры
************************************** Без иерархии: 797 Кол-во: 1000 С иерархией: 957 Кол-во: 1000 Фильтр6: 240 Кол-во Фильтр6: 1000 ************************************** Без иерархии: 810 Кол-во: 1000 С иерархией: 921 Кол-во: 1000 Фильтр6: 216 Кол-во Фильтр6: 1000 ************************************** Без иерархии: 832 Кол-во: 1000 С иерархией: 920 Кол-во: 1000 Фильтр6: 222 Кол-во Фильтр6: 1000 ************************************** Без иерархии: 764 Кол-во: 1000 С иерархией: 1502 Кол-во: 34142 Фильтр6: 1036 Кол-во Фильтр6: 34142 ************************************** Без иерархии: 701 Кол-во: 1000 С иерархией: 1538 Кол-во: 34142 Фильтр6: 972 Кол-во Фильтр6: 34142 ************************************** Без иерархии: 9 Кол-во: 1 С иерархией: 117 Кол-во: 7289 Фильтр6: 165 Кол-во Фильтр6: 7289 ************************************** Без иерархии: 9 Кол-во: 1 С иерархией: 120 Кол-во: 7289 Фильтр6: 170 Кол-во Фильтр6: 7289 ************************************** Без иерархии: 9 Кол-во: 1 С иерархией: 118 Кол-во: 7289 Фильтр6: 183 Кол-во Фильтр6: 7289 ************************************** Без иерархии: 54 Кол-во: 1 С иерархией: 214 Кол-во: 7289 Фильтр6: 194 Кол-во Фильтр6: 7289 ************************************** Без иерархии: 10 Кол-во: 1 С иерархией: 36 Кол-во: 58 Фильтр6: 61 Кол-во Фильтр6: 58 ************************************** Без иерархии: 10 Кол-во: 1 С иерархией: 51 Кол-во: 58 Фильтр6: 81 Кол-во Фильтр6: 58 ************************************** Без иерархии: 11 Кол-во: 1 С иерархией: 37 Кол-во: 58 Фильтр6: 61 Кол-во Фильтр6: 58 ************************************** Без иерархии: 12 Кол-во: 1 С иерархией: 43 Кол-во: 58 Фильтр6: 67 Кол-во Фильтр6: 58 |
|||
31
dk
25.01.19
✎
12:42
|
если в фильтре тока группы, то проигрывает чутка если в абсолюте смотреть
а на смешанных списках выигрывает от 40% до 800% |
|||
32
dk
25.01.19
✎
12:43
|
может найдутся энтузиасты которые в скуле реализуют уложитьсписокобъектов
|
|||
33
trad
25.01.19
✎
13:32
|
//*******************************************
Процедура УложитьСписокОбъектов(пСЗ, пИмяТаблицы, пВидСправочника = "") ТЗ = СоздатьОбъект("ТаблицаЗначений"); пСЗ.Выгрузить(ТЗ); рс = СоздатьОбъект("ODBCRecordset"); рс.ВыполнитьИнструкцию(" |if exists(select * from tempdb..sysobjects where id = object_id('tempdb.." + пИмяТаблицы + "')) | drop table " + пИмяТаблицы + " |create table " + пИмяТаблицы + " (val char(9) collate database_default, isfolder tinyint, primary key clustered (val)) |"); рс.Подготовить("insert into " + пИмяТаблицы + " values (?, 2)"); рс.ДобПараметр(1, 14, 9, 0); рс.ВыполнитьSQL_ИзТЗ(ТЗ); рс.Закрыть(); Если ПустаяСтрока(пВидСправочника) = 0 Тогда рс.ВыполнитьИнструкцию(" |set nocount on | |update " + пИмяТаблицы + " |set | isfolder = 1 |from " + пИмяТаблицы + " tab |inner join $Справочник." + пВидСправочника + " as ref (nolock) on ref.id = tab.val |where | ref.isfolder = 1 | |declare @folders table(val char(9) collate database_default, primary key clustered (val)) |while 1=1 begin | | insert into @folders | select | val | from " + пИмяТаблицы + " tab | where tab.isfolder = 1 | | if @@rowcount = 0 | break | | insert into " + пИмяТаблицы + " | select | id, | isfolder | from $Справочник." + пВидСправочника + " (nolock) | where | parentid in (select val from @folders) and | id not in (select val from " + пИмяТаблицы + ") | | delete " + пИмяТаблицы + " | where | val in (select val from @folders) | |end |delete @folders | |set nocount off |"); КонецЕсли; КонецПроцедуры |
|||
34
trad
25.01.19
✎
13:33
|
(32) что значит "в скуле реализуют" ?
|
|||
35
trad
25.01.19
✎
13:36
|
(33)
************************************** Без иерархии: 770 Кол-во: 3000 Без иерархии2: 115 Кол-во: 3000 С иерархией: 836 Кол-во: 3286 С иерархией2: 201 Кол-во: 3286 ВыполнитьSQL_ИзТЗ: 116 Кол-во: 3000 |
|||
36
trad
25.01.19
✎
13:37
|
(33) - это реализация моего предложения в (16)
|
|||
37
dk
25.01.19
✎
13:59
|
(33) спасибо - самый шустрый вариант
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |