Вход | Регистрация
 
1С:Предприятие :: 1С:Предприятие 7.7 и ранее

v7: 1с++ ускорение Запрос.УложитьСписокОбъектов

v7: 1с++ ускорение Запрос.УложитьСписокОбъектов
Я
   dk
 
21.01.19 - 12:12
исходные:
1с++, SQL 2000 / 2008
Проблема:
Довольно долго укладываются большие списке объектов (1000 элементов и больше)

Без иерархии: 2430 мс
С иерархией: 2394 мс
ВыполнитьSQL_ИзТЗ: 229 мс

Ниже замеры и код
 
 
   dk
 
1 - 21.01.19 - 12:13
Процедура Сформировать()

    Запрос = СоздатьОбъект("ODBCRecordSet");
    
    ТекстЗапроса = "SELECT TOP 3000 ID [Счет $Справочник.Счета] FROM $Справочник.Счета (NOLOCK)";
    
    ВремТЗ = СоздатьОбъект("ТаблицаЗначений");
    
    Запрос.ВыполнитьИнструкцию(ТекстЗапроса, ВремТЗ);
    
    СЗ_Фильтр = СоздатьОбъект("СписокЗначений");
    ВремТЗ.Выгрузить(СЗ_Фильтр,,,"Счет");
    
    //СЗ_Фильтр.ВыбратьЗначение(1);

    
    Сообщить("**************************************");
    
    Нач = _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 (Счет))";
        
    Запрос.ВыполнитьИнструкцию(ТекстЗапроса);    
    
    Запрос.Подготовить("INSERT INTO #Фильтр3 VALUES(?)");
    Запрос.ВыполнитьSQL_ИзТЗ(ВремТЗ);
    Сообщить("ВыполнитьSQL_ИзТЗ: " + (_GetPerformanceCounter() - Нач));
    Сообщить("Кол-во: " + Запрос.ВыполнитьСкалярный("SELECT COUNT(*) FROM #Фильтр3"));
    
КонецПроцедуры

   dk
 
2 - 21.01.19 - 12:16
Собственно вопрос 
кто-то занимался ускорением уложитьсписок объектов?
либо есть универсальный запрос по получению иерархии шустрый?
   trad
 
3 - 21.01.19 - 12:19
а если так?
CREATE TABLE #Фильтр3 (Счет Char(9), PRIMARY KEY CLUSTERED (Счет))
   dk
 
4 - 21.01.19 - 12:23
(3) пофигу
**************************************
Без иерархии: 2370
Кол-во: 3000
С иерархией: 2590
Кол-во: 3000
ВыполнитьSQL_ИзТЗ: 221
Кол-во: 30
   dk
 
5 - 21.01.19 - 12:23
Кол-во: 3000
   trad
 
6 - 21.01.19 - 12:25
затестил у себя (на $Справочник.Номенклатура):

**************************************
Без иерархии: 890
Кол-во: 3000
С иерархией: 1062
Кол-во: 3286
ВыполнитьSQL_ИзТЗ: 127
Кол-во: 3000
   dk
 
7 - 21.01.19 - 12:26
ну гдето в 7-8 раз шустрее
   Туц
 
8 - 21.01.19 - 12:27
Альтернатива это импорт из командной строки.
   Mikeware
 
9 - 21.01.19 - 12:36
а нужен ли такой список? может, его сразу формировать во временной таблице запросом?
   Туц
 
10 - 21.01.19 - 12:36
Кстати через adodb можно бинарник пихнуть ввиде xml
 
 Рекламное место пустует
   dk
 
11 - 21.01.19 - 12:38
(9) ну это например может быть какой-то охрененный список товаров из Excel загружен в несколько тыс строк или группа первого уровня
   Туц
 
12 - 21.01.19 - 12:45
Ещё вариант. Укладывать не таблицу и список строк. Т.е. строку таблицы приводить суммировать в строку. Чисто в теории будет кратный количеству колонок выйгрышь
   Mikeware
 
13 - 21.01.19 - 12:48
(11) так по идее по адо можно сразу из экселя...
а группу первого уровня можно запросом собрать
   trad
 
14 - 21.01.19 - 12:48
имхо, проблема в медленном итерировании списка внутрях УложитьСписокОбъектов
   Sserj
 
15 - 21.01.19 - 12:48
(11) Если список товаров то ничего не сделаешь. А если группа первого уровня, да и вообще любая группа лучше сделать через CTE фильтр групп и условие по родителю.
   trad
 
16 - 21.01.19 - 12:50
вердикт. сделать свой УложитьСписок на основе ВыполнитьSQL_ИзТЗ.
Разворот иерархии написать самому или спиимствовать у УложитьСписок
   dk
 
17 - 21.01.19 - 12:53
(15) sql 2000 не дружит с cte
(16) угу, смотрю профайлером как штатный робит и как выполнитьтз
   Вафель
 
18 - 21.01.19 - 12:55
а зачем нежен фильтр из 3000 элементов?
   Sserj
 
19 - 21.01.19 - 12:56
(17) Ну там в топике 2008 было написано. Ради CTE да оконных функций можно было бы и поднапрячься с переходом на посвежее :)
   dk
 
20 - 21.01.19 - 12:59
(18) см (11)
   Mikeware
 
21 - 21.01.19 - 13:06
(16) другими словами, не использовать универсальный способ, на написать частный для частных случаев.
   trad
 
22 - 21.01.19 - 13:08
(21) честно сказать, я удивлен, что неиерархический УложитьСписокОбъектов так проигрывает ВыполнитьSQL_ИзТЗ
   Mikeware
 
23 - 21.01.19 - 13:15
(22) из-за универсальности. но да, проигрыш слишком велик...
   trad
 
24 - 21.01.19 - 13:33
так дело в том, что УложитьСписок не имеет какой-то там универсальности.
То, что он умеет еще делать запрос по развороту иерархии, не влияет на само "укладывание"
То, что в таблице есть еще служебное поле "isfolder", тоже не сказывается
   Salimbek
 
25 - 21.01.19 - 15:46
(24) Может кто допилит на использование Массив, Структура, Соответствие или чего еще быстрого (мечтательно) :-)
   ADirks
 
26 - 22.01.19 - 08:50
(25) Нет смысла, т.к. накладные расходы на уровне СУБД на порядок (порядки?) больше, чем на исполнение кода 1С.

Самостоятельная реализация УложитьСписок() в данном случае полезна в исследовательских целях, а то действительно непонятно, откуда такие тайминги.
   Дык ё
 
27 - 22.01.19 - 09:12
(16) какое чудесное слово - "спиимствовать" :)

а включение режимrpc на тайминги уложитьсписок не влияет?
   trad
 
28 - 22.01.19 - 14:24
(27) режимrpc на уложитьсписок не влияет
   dk
 
29 - 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"));    

    
КонецПроцедуры
   dk
 
30 - 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
   dk
 
31 - 25.01.19 - 12:42
если в фильтре тока группы, то проигрывает чутка если в абсолюте смотреть
а на смешанных списках выигрывает от 40% до 800%
   dk
 
32 - 25.01.19 - 12:43
может найдутся энтузиасты которые в скуле реализуют уложитьсписокобъектов
   trad
 
33 - 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
        |");
    КонецЕсли;
    
КонецПроцедуры
 
 
   trad
 
34 - 25.01.19 - 13:33
(32) что значит "в скуле реализуют" ?
   trad
 
35 - 25.01.19 - 13:36
(33)
**************************************
Без иерархии: 770
Кол-во: 3000
Без иерархии2: 115
Кол-во: 3000
С иерархией: 836
Кол-во: 3286
С иерархией2: 201
Кол-во: 3286
ВыполнитьSQL_ИзТЗ: 116
Кол-во: 3000
   trad
 
36 - 25.01.19 - 13:37
(33) - это реализация моего предложения в (16)
   dk
 
37 - 25.01.19 - 13:59
(33) спасибо - самый шустрый вариант


Список тем форума
Рекламное место пустует  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.
Рекламное место пустует