Имя: Пароль:
1C
1C 7.7
v7: Ускорить операции с ТЗ
,
0 Злопчинский
 
03.12.11
10:18
Прошу совета апологетов 1С++
.
кучу времени в расчетах жрет конструкция
.
Функция глОтобратьПоКолонке(ТЗВход,Колонка,Значение)
Экспорт //возвращает отобранную ТЗ
   Перем ТЗ, ТЗВрем;
   ТЗВход.Выгрузить(ТЗ); //вот здесь, сволочь!
.
..функция возвращает ТЗ, отфильтрованную по заданному значению заданной колонки...
.
можно конечно ускорить, заменив выгрузку на ТЗ.Заполнить(ТЗВход)
.
может еще что есть для ускорения...?
может под это дело как-то подойдкт индексированная таблица?
1 DEVIce
 
03.12.11
10:20
Индексированная таблица как-то подойдет - да. :)
2 Mikeware
 
03.12.11
10:22
Уточни задачу
3 zak555
 
03.12.11
10:22
лучше забить на это дело и пойти погулять
4 DEVIce
 
03.12.11
10:24
В ИТ вообще можно задать индекс, от фильтровать по нему и работать уже с использованием этого индекса, без всяких выгрузов в ТЗ и прочих извращений. Но я уже не помню как это точно сделать, давно 1сpp не баловался.
5 Злопчинский
 
03.12.11
10:27
(2) из большой ТЗ надо выдрать подмножество строк; строки попадающие в подмножество фильтруются по значению заданной колонки

//есть некая ТЗ
ТЗподмножество = глОтобратьПоКолонке(ТЗ,"Контрагент",выбКонтрагент);
- в ТЗподмножество будут только те строки исходной ТЗ, где ТЗ.Клиент=ВыбКлиент
6 Злопчинский
 
03.12.11
10:28
тьху...
..где где ТЗ.Контрагент=ВыбКонтрагент
7 Mikeware
 
03.12.11
10:28
ДобавитьИндекс / AddIndex

   Описание: Добавляет индекс к таблице.

   Синтаксис: ДобавитьИндекс(стрИдентификатор, стрВыражение, [чТолькоУникальныеЗначения = 0])

   Параметры

           * стрИдентификатор - строка, идентификатор создаваемого индекса;
           * стрВыражение - строка, индексное выражение. Индексное выражение состоит из списка идентификаторов колонок, разделённого запятыми. Если перед именем колонки стоит символ '-', то сортировка осуществляется в обратном порядке. Если перед именем колонки стоит символ '*', то сортировка осуществляется в по внутреннему представлению объекта. Если перед именем колонки стоит символ '#', то перед сравнением строк обрезаются пробелы слева и справа. Если перед именем колонки стоит символ '^', то строки сравниваются без учёта регистра. Модификаторы сортировки ('-', '*', "#", "^") можно использовать в любых сочетаниях. Индексное выражение может быть пустой строкой - это эквивалентно сортировке по номеру строки, или отсутствию сортировки (фильтр на такой индекс установить нельзя).
           * чТолькоУникальныеЗначения - число. Если 1, то в индекс попадут только строки, содержащие уникальные значения индекса. Строки с повторяющимися индексами будут проигнорированы, и в операции перебора строк, суммирования, свёртки, выгрузки, загрузки не попадут.

   Возвращаемое значение: число, номер созданного индекса.



УстановитьФильтр / SetFilter

   Описание: устанавливает динамический фильтр на таблицу по указанному индексу. Фильтр влияет на работу методов: ВНачало(), ВыбратьСтроки(), ВКонец(), ПолучитьСтроку(), СледующаяСтрока(), ПредыдущаяСтрока(),Свернуть(),Итог(), ЗаполнитьКолонку(), Выгрузить(), Загрузить(), Объединить().

   Синтаксис: УстановитьФильтр(КлючМин, КлючМакс, [Индекс = ""], [чТолькоУникальные = 0])

   Параметры

           * КлючМин - нижняя граница фильтра. Задаётся так же, как в методе НайтиСтроку().
           * КлючМакс - верхняя границы фильтра. Задаётся так же, как в методе НайтиСтроку().
           * Индекс - идентификатор или номер индекса. По умолчанию используется основной индекс.
           * чТолькоУникальные - число, если 1 - то в выборку попадут только строки с уникальным значением ключа.

       Если индекс построен по одной колонке, то в качестве ключей можно использовать значение колонки. Если же индекс по нескольким колонкам, то ключ должен быть СписокЗначений, содержащий значения ключевых колонок, заданных в методе ДобавитьИндекс().
8 Злопчинский
 
03.12.11
10:29
исходная ТЗ м.б. от одной до нескольких тысч строк
9 Mikeware
 
03.12.11
10:32
(5) Нечто типпо

ИТЗ.Загрузить(ВходящаяТЗ)
ИТЗ.ДобавитьИндекс("ПоКонтре","Контрагент",0);
ИТЗ.УстановитьФильтр(ВыбКонтрагент,ВыбКонтрагент,"ПоКонтре");
ИТЗ.Выгрузить(ВыходнаяТЗ)
10 Mikeware
 
03.12.11
10:33
Только можно и не загружать-выгружать, а просто накладывать фильтр, и работать как с обычной ТЗ. Зависит от задач
11 Злопчинский
 
03.12.11
10:33
(7) а по товим оценкам замена на (7) даст существенный прирост скорости?
.
добавляю индекс из одной колонки, потом ставлю фильтр, и иду простой выборкой по таблице - получаю только то, что попало в фильтр...?
.
а если второй раз устанавливаю фильтр - первый фильтр сбросится и установится второй..?
12 Mikeware
 
03.12.11
10:35
(11) Ебстебственно...
На больших таблицах прирост скорост скорости большой. На мелких - есть даже падение. Таки накладняк :-)
13 Злопчинский
 
03.12.11
10:38
(10) > а просто накладывать фильтр, и работать как с обычной ТЗ.
- да, это подойдет...
.
а после наложения фильтра - исходный порядок строк останется...?
14 Mikeware
 
03.12.11
10:40
(13) Вроде не гарантируется.
Но ставь составной индекс, проблем-то..
15 Злопчинский
 
03.12.11
10:41
(12) в принципе можно и штатной ТЗ обойтись...
.
ТЗ.Сортировать("Контрагент,ОригинальныйПорядокСтрок");
- потом для контрагента - позиционироваться поиском на нужного, и идти обычной выборкой пока контрагент не сменится.. - при таком подходе, скорее всего наверное производительность будет соизмерима с индексированной...
16 Mikeware
 
03.12.11
10:42
(15) Способ фактически тот же, но на больших таблицах индексированная быстрее.
17 Mikeware
 
03.12.11
11:09
Ну и? помощь нужна еще, или победил?
18 Злопчинский
 
03.12.11
11:13
(16) а, блин, как в (15) не получится.. нужен итог по числовой колонке...
ИТЗ дает Итог() по фильтру - это хорошо...
.
(14) составной индекс - это как будет..? надо чтобы был фильтр наложен, и строки шли по оригинальном упорядку строк (колонка, например, "ОПС") - мог усоздать составнйо индекс, а фильтровать по только по однйо части составного индекса..? типа так?
19 Mikeware
 
03.12.11
11:16
(18) Нет, фильтровать надо по всему индексу.
Но минимальный ключ у тебя будет {Контрагент,0}, а максимальный {Контрагент, КолСтрок_ИТЗ}
20 DEVIce
 
03.12.11
11:30
(14). Остается, потому что существует индекс по умолчанию.
21 DEVIce
 
03.12.11
11:33
(18). МОжно создать сразу несколько индексов. Я делал, например, по контрагенту и по контрагенту/договору. Потом выборкой проходил по контрагенту и следующей по контрагенту/договору. Очень удобно. В случае с ТЗ пришлось бы делать одну ТЗ копированием другой и потом сварачивать по контрагенту, а затем реализовавать обход с поиском по двум полям в первоначальной. А если таких полей 5-6? Вооот. Тут ИТ здорово помогает, это кроме скорости работы.
22 Mikeware
 
03.12.11
11:34
(20) Индекс по умолчанию - по номеру строки. Ты назначаешь новый индекс. Который к индексу по умолчанию никакого отношения не имеет. В общем-то, по всем правилам, порядок сток в выборке при отсутсвии явного указания сортировки - не гарантируется. Судя по опыту работы с ИТЗ - на "по умолчанию" в ней лучше не полагаться. Судя по стилю, писали люди, помнящие анекдот про яблоки и буратино....
23 DEVIce
 
03.12.11
11:40
(22). Это на до у Диркса уточнить. Насколько помню один индекс не влияет на другой.
24 DEVIce
 
03.12.11
11:41
(22). Что за анекдот?
25 Mikeware
 
03.12.11
11:42
(23) Естественно, не влияет. О чем я и говорю - что "индекс по умолчанию" - по номеру строки - никак не повлияет на построение индекса по контре. Т.е. порядок в доступе по индексу по контре никак не связан с порядком строк. он _может_ быть построен в "порядке исходных строк", но не обязан.
26 Mikeware
 
03.12.11
11:43
(24) Буратино дали три яблока. Два он съел. Сколько яблок осталось у Буратино? Думаете одно? Ничего подобного. Никто не знает сколько у него уже было яблок до этого. Мораль: всегда обнуляйте переменные!
©
27 DEVIce
 
03.12.11
11:45
(25). Ну так ты раз отсортируй и порядок потом не изменится при манипуляции с другими индексами.
28 Mikeware
 
03.12.11
11:45
(27) Не уверен, и поставщиком это нигде не описано. на неописанные вещи предпочитаю не опираться....
29 DEVIce
 
03.12.11
11:46
(26). "Барутино, предположим ты дал 2 яблока некту, сколько у тебя останется? Да я не дам 2 яблока некту - хоть он дерись" :)
30 DEVIce
 
03.12.11
11:47
Плохо что Алексей по форумам не лазит - он бы сейчас точно сказал. :)
31 Злопчинский
 
03.12.11
11:48
(19) не понял..а!! и будет тогда в фильтре упорядочено от Мин до Макс индекса?
32 DEVIce
 
03.12.11
11:51
(31). А вот ту не обязательно, сортировать все-таки надо.
33 DEVIce
 
03.12.11
11:53
(31). Вообще на www.1cpp.ru написано подробнее.
34 Mikeware
 
03.12.11
11:59
(32) Вот тут как раз обязательно. Ибо индекс
35 DEVIce
 
03.12.11
12:01
(34). Ты меня запутал :). По умолчанию тоже индекс, с техническо точки зрения точно такой же, что и ручками добавленный.
36 DEVIce
 
03.12.11
12:02
Все, я поехал в танчики рубиться. С индексами вашими тут в субботу понимаешь :)
37 Mikeware
 
03.12.11
12:05
(35) "Индекс по умолчанию" не имеет никакого отношения к вновь построенному индексу.
Если индекс по {Контра, номер строки}, то и сортировка никакая не нужна - при доступе по индексу доступ будет эквивалентенн сортировке сначала по контре, внутри контры - по номеру строки.
Если индекс только по контре - то при доступе по индексу - по контре будут отсортированы,  а как в пределах одной контры - не гарантировано. Может, по номеру строки, а может как-то иначе.
38 Злопчинский
 
03.12.11
13:16
(37) по идее, нормально получится с составным индексом. Если прирост ощутимый будет - то ок. Штатный вариант подошел бы, но блин итог по таблице нужен по фильтру по количеству. Спасибо за помощь всем...
.
пошел руками поработаю - унитаз попробую починить.. это для меня круто!
39 Torquader
 
03.12.11
22:58
А если сразу при создании ТЗ отбирать по нужной колонке ?
40 Aleksey
 
03.12.11
23:03
Я для таких задач юзаю группировать

ИТЗ.Группировать("Контрагент:Контрагент","КлонкаССуммаЕслиНадо");

А дальще хоть поиск (ТЗ маленькая)
Хоть перебор

ИТЗ.ВыбратьСтроки();
Пока ИТЗ.ПолучитьСтроку()=1 цикл
  //вторая ТЗ по этому контру
  ВтораяТЗ=ИТЗ.тзПотомки;
  ВтораяТЗ.ВыбратьСтроки();
....
41 Aleksey
 
03.12.11
23:04
42 Злопчинский
 
04.12.11
15:27
(40) каков порядок строк в ТЗпотомки?
43 Злопчинский
 
04.12.11
17:28
(39) можно и так, попробую попозже... если ИТЗ не даст прироста планируемого
44 Aleksey
 
04.12.11
17:29
(42) Непроверял, скорее всего тот же что и был.
В любом случае

ВтораяТЗ=ИТЗ.тзПотомки;  - это ТЗ, а значит

ВтораяТЗ.Сортировать("нужнаяКолонка") будет работать
46 Злопчинский
 
04.12.11
17:48
(44) да, сейчас пробую; запрограммил, запущу на тестовый длительный просчет - если где-то криво - выплывет сразу...
.
подошло создание фильтра, потом группировка по фильтру с итогом по количеству, а далее "шатный" алгоритм: прямо берется тзПотомки по ссылке и сортируется по ОПС (оригинальный порядок строк).. сейчас прроверим...
47 Злопчинский
 
04.12.11
17:49
такс.. не получается с группировкой...
48 Злопчинский
 
04.12.11
17:50
а! при Группировать предварительно индекс не надо сосздавать!
49 Злопчинский
 
04.12.11
17:55
О! запустился.. чисто визуально даже видно вроде как есть ускорение...
50 Злопчинский
 
04.12.11
18:01
итого получилось так, как посоветовали выше - легло иделаьно в код
.
ИТЗ = СоздатьОбъект("ИндексированнаяТаблица");
ИТЗ.Загрузить(ТЗгтд);
ИТЗ.Группировать("ФильтрНоменклатура: Номенклатура","Количество");
//
//найдем и спозиционируемся
Если ИТЗ.НайтиСтроку("ФильтрНоменклатура", текНоменклатура, 0, 1) = 0
Тогда //сюда попадать не должны
 Сообщаить("Алярм-001!","!!!");
 Продолжить;
КонецЕсли;

ТЗгтдНоменклатура = ИТЗ.тзПотомки;
Если ИТЗ.Количество < ОстПогКоличество
Тогда
51 Aleksey
 
04.12.11
18:12
Угу самому иногда не хватает в 8-ке такой же легкой группировки
52 Злопчинский
 
04.12.11
20:04
(51) а что, в 8-ке нельзя ТЗ подсунуть в запрос и получить на выходе что надо...?
53 Дядя Васька
 
04.12.11
20:11
(52) Там и без запроса можно по нескольким полям отобрать. Метод НайтиСтроки(), и индексы тоже есть.
54 Aleksey
 
04.12.11
20:39
(53) Вопрос то не в найти строки, а именно группировки. Т.е. построение дерево


Очень часто нужно с плюсиками выводить отчет с кучей вложенной группировки, и ИМХО метод "НайтиСтроки()" будет сильно затратен, не говоря уж о том, что для начало нужно получить те значения которые нужно искать
55 Злопчинский
 
04.12.11
21:19
ух, блин, переколбасил весь алгоритм... ща буду тестить...
56 Злопчинский
 
04.12.11
21:40
так, блин, непонятно...
чегой-то не видно после группировки чтобы была ТЗПотомки
57 Злопчинский
 
04.12.11
21:40
а кто объяснит, почему вот это нифига не работает...
.
//*******************************************
Процедура Сформировать()

   ТЗ = СоздатьОбъект("ТаблицаЗначений");    
   ТЗ.НоваяКолонка("Ключ","Строка");
   ТЗ.НоваяКолонка("Значение","Строка");
   ТЗ.НоваяКолонка("Количество","Число");
   
   ТЗ.НоваяСтрока();
   ТЗ.Ключ = "строка1";
   ТЗ.Значение = "значение1";
   ТЗ.Количество = 1;

   ТЗ.НоваяСтрока();
   ТЗ.Ключ = "строка1";
   ТЗ.Значение = "значение2";
   ТЗ.Количество = 3;
   
   ТЗ.НоваяСтрока();
   ТЗ.Ключ = "строка2";
   ТЗ.Значение = "значение1";
   ТЗ.Количество = 2;
   
   ИТЗ = СоздатьОбъект("ИндексированнаяТаблица");
   ИТЗ.Загрузить(ТЗ);
   ИТЗ.Группировать("ФильтрТипа: Ключ","Количество");
   ИТЗ.ВыбратьСтроку(,);
   
КонецПроцедуры
58 Злопчинский
 
04.12.11
22:22
так, уже объяснили! ура!
59 Злопчинский
 
05.12.11
01:51
Если индекс составной, например, "ГТД,Документ"
то как на ИТЗ наложить фильтр, чтобы осталась выборка только конкретного ГТД..???
.
люди, ау!!!
60 ОбычныйЧеловек
 
05.12.11
01:54
(59) Если хочешь получить ответ то лучше сюда http://www.1cpp.ru/forum/YaBB.pl
61 Дядя Васька
 
05.12.11
02:01
(54) Ну вроде как ветка началась именно с этого. К сортировкам с группировками пришли уже после, дабы избежать тормозов при копировании. НайтиСтроки() ничего не копирует, просто возвращает массив ссылок на нужные строки, что по сабжу и требовалось.
62 Злопчинский
 
05.12.11
02:21
А вот вопрос Индекс по "Документ", где документ - любого вида - как упорядочивает..?
63 Злопчинский
 
05.12.11
02:21
(61) убить нахрен надо тех кто доки пишет невразумительные...
64 Vakhrin
 
05.12.11
03:13
а еще выборки разные из больших ТЗ можно вот так ускорить: http://vakhrin.com/?p=19#more-19 ;)
65 КонецЦикла
 
05.12.11
03:32
(59) Передавать список значений (вроде так обычно делается)
Например для поиска:

ИТЗУпаковки.ДобавитьИндекс("ИндТовар", "Товар,Серия,СрокГодности");
...
Спис = СоздатьОбъект("СписокЗначений");
               Спис.ДобавитьЗначение(ТекТовар,                    "Товар");
               Спис.ДобавитьЗначение(ТЗРезервов.Серия,            "Серия");
               Спис.ДобавитьЗначение(ТЗРезервов.СрокГодности,    "СрокГодности");
               
               НомСтр = ИТЗУпаковки.НайтиСтроку("ИндТовар", Спис, , 1);

По фильтрам нету, сорри, как-то обходился все время без них :)

Если есть какой-то большой набор данных, обрабатываемый многократно... ну типа в качестве бреда, не будет ли быстрее создать временную таблицу SQL или чо там у тебя, и делать выборку по индексу?
66 Злопчинский
 
05.12.11
03:43
Отдельная благодарность  Aleksey'ю за оказанные помощь/консультации!!!
оееееееееееееееееееее! хренячит быстро офигенно! не то что на штатных ТЗ (хотя логику сохранил практически одинаковую). Реальный выигрыш по предварительным замерам на массовом перепроведении будет примерно в 5 раз... как минимум.. уаааааааааааааа! я ж теперь в два раза больше сена накосю!!!
67 Злопчинский
 
05.12.11
03:48
(65) предварительные исследования показали что Ус фильтром не получится так (УстановитьФильтр), если надо наложить фильтр на составнйо индексс пропуском полей индекса - использовали ИТЗ.Подмножество().
.
про временную таблицу SQL - это мысль, конечно, но а) база дбфная, придется изворачиваться нескульными провайдерами б) есть сомнения что будет ощутимый прирост.. индексированная ТЗ - имхо почти то же самое...
.
а вот перевести на прямые запросы РассчитатьИтогиНа() - это можно попробовать (но опять же на дбф, у меня движок сетевой нескульный, а то ябы давно на скуль перевел, благо и скуль лицензионный есть и все остальное).
.
опять же - еще ускорение РассчитатьРегистрыНа для перепроведения задним числом (ЗЧ) даст наверное период итогов на 5 дней - но это уже на след.выходные буду пробовать...
68 Злопчинский
 
05.12.11
03:51
хотя хз.. эксперимент не сильно чистый, сисадмин учерась дефраг на диски с базой сделал.. может еще и это эффект дало... ;-) хотя вряд ли что это сильно повлияло.. ибо диск под базу выделен отдельный физический и почти там ничего больше и не лежит/неиспользуется...
.
а вот интересно.. размер кластера при работе на дбфе по идее может дать кое-какие профиты...?
69 Злопчинский
 
05.12.11
05:22
в итоге: реальный выигрыш получился раза в три... именно на операциях с ТЗ...
на фоне общих временных затрат выигрыш не так существене.. все сжирает временные итоги РассчитатьРегистрыНа() - как это ускорить...?
70 Злопчинский
 
05.12.11
06:05
мдя... последнйи релиз 1С++ датирован 13.08.2010 г.
скоро полтора года как ничего не изменилось...
можно считать, что прект умер.
пора линять на снеговика...
71 SnarkHunter
 
05.12.11
06:57
Последний релиз 1С++ (3.2.3.17) датирован 01.12.2011...
72 SnarkHunter
 
05.12.11
06:58
>> все сжирает временные итоги РассчитатьРегистрыНа() - как это ускорить

Прямыми запросами...
73 Злопчинский
 
05.12.11
07:12
меня плющит..?
на 1Сpp в снапшотах последний 3.2.2
http://s017.radikal.ru/i403/1112/33/b62f80e0b087.png
74 Злопчинский
 
05.12.11
07:13
(72) вообщем это понятно.. ;-) но вот в частностях...
75 SnarkHunter
 
05.12.11
07:30
(73)Релизы выкладываются на форуме в специальной ветке...
76 Злопчинский
 
05.12.11
07:33
(75) ну хоть бы написали на сайте в разделе снапшотов ссылку на форум
кто в лес, кто по дрова...
77 SnarkHunter
 
05.12.11
07:38
(76)Что есть, то есть... :-)
78 ЧеловекДуши
 
05.12.11
08:08
(73)Это старая информация и не соответствует действительности :)
79 Злопчинский
 
05.12.11
13:42
(78) ну уж если на офиц.странице актуальность не поддерживают - проект тихонько умирает...
Оптимист верит, что мы живем в лучшем из миров. Пессимист боится, что так оно и есть.