Как оптимизировать данный код?

1. 2 07.04.21 18:27 Сейчас в теме
Как вы думаете, можно ли оптимизировать данный код? Как? Что будет результатом этого кода?

Для а = -ТаблицаЗначений.Количество() + 1 по 0 Цикл
Стр = ТаблицаЗначений[-а];
Если Стр.Количество = 0 Тогда
ТаблицаЗначений.Удалить(Стр);
КонецЕсли;
КонецЦикла;
Ответы
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
2. nomad_irk 55 07.04.21 18:31 Сейчас в теме
(1)использовать метод НайтиСтроки() вместо тупого перебора всей ТЗ.
FatPanzer; ImHunter; Fox-trot; +3 Ответить
9. Nefilimus 41 07.04.21 20:30 Сейчас в теме
(1) сделать запрос по данной таблице значений, поставить условие количество <> 0. Полученный результат выгрузить в другую таблицу значений. Если есть шанс, что и дальше в коде будете работать полученной таблицей значения, то в запросе используйте ещё и менеджер временных таблиц. Думаю больше некуда оптимизировать
18. FatPanzer 13 08.04.21 09:23 Сейчас в теме
(9) А зачем в СУБД? Давайте сразу превратим ТЗ в массив структур, пройдемся по каждой структуре, поудаляем элементы массива, в структуре которых нужные ключи = 0, потом обратно из массива структур сделаем ТЗ...

Можно еще в XML сериализовать, перевести в DOM-модель, и с помощью выражений XPath поудалять нулевые элементы, вернуть обратно в XML, и десериализовать обратно в ТЗ...
nomad_irk; Nefilimus; SlavaKron; +3 Ответить
25. Nefilimus 41 08.04.21 12:19 Сейчас в теме
(18) был у меня случай, где в ТЗ было больше 100000 записей. Как вы думаете, перебрать их строкой это правильно?
26. Sashares 18 08.04.21 12:23 Сейчас в теме
(25)Вы считаете, что нет?
nomad_irk; Nefilimus; +2 Ответить
27. Nefilimus 41 08.04.21 12:25 Сейчас в теме
(26) включите замер производительности, и пройдитесь в одном коде по циклу к таблице несколько раз, а потом тоже самое но используя уже созданную временную таблицу и проверьте разницу
28. Sashares 18 08.04.21 12:30 Сейчас в теме
(27)Зачем проходить несколько раз?
В зависимости от задачи можно предложить разные варианты решения.
Если цель - из таблицы в 100000 строк получить другую таблицу, в которой только часть строк, то в общем случае можно в таблицу добавить колонку булевую, заполнить ее значением Истина для нужных строк и скопировать исходную таблицу с отбором по этой колонке.
В частных случаях, когда условие на равно, даже колонки добавлять не надо.

Если у вас есть реальные данные для теста, можете попробовать и сделать замер, у меня их нет.
Nefilimus; +1 Ответить
29. Nefilimus 41 08.04.21 12:35 Сейчас в теме
(28) на данный момент под рукой нет. Но делал подобную задачу клиенту, поверьте через запрос намного быстрее
30. nomad_irk 55 08.04.21 12:36 Сейчас в теме
(29)Не поверю, пока не покажите замер производительности :)
35. Nefilimus 41 08.04.21 14:11 Сейчас в теме
36. nomad_irk 55 08.04.21 14:21 Сейчас в теме
(35) уж простите, но джентельменам на слово не верю :)
Nefilimus; +1 Ответить
32. spacecraft 08.04.21 13:08 Сейчас в теме
(29) тестировали в файловой базе через отладчик? Тогда возможно.
34. Nefilimus 41 08.04.21 14:09 Сейчас в теме
(32) нет, был клиент-серверный вариант. Через отладчик)
10. dandykry 6 08.04.21 06:59 Сейчас в теме
(1)

сч= ТаблицаЗначений.Количество();

Пока сч <> 0 Цикл

сч = сч - 1;

СтрокаТЧ = ТаблицаЗначений[0];

Если СтрокаТЧ.Количество = 0 Тогда
ТаблицаЗначений.Удалить(СтрокаТЧ);
КонецЕсли;

КонецЦикла;


Самый оптимальный вариант.
Передавать как параметр в запрос мега глупая идея, потому что мало того такая операция считается ресурсоемкой, так помимо сервера 1с еще задействуется сервер sql, который возможно является другой машиной в сети, до которой по сети нужно таблицу передать. В свою очередь сервер sql сделает тоже самое - пробежится по всей таблице и удалит все строи из нее, и потом вернет результат, опять же возможно по сети.

НайтиСтроки - Сделает приблизительно тоже самое - пробежится по таблице и сравнит значение в колонке и запишет в массив строк, которые ты опять же должен удалить. Можно поэксперементировать на больших таблицах что быстрее - обойти циклом с конца и удалить или сначала найти все строки и после поштучно их удалить. Думаю первый вариант лучше.
19. dandykry 6 08.04.21 09:39 Сейчас в теме
(10) СтрокаТЧ = ТаблицаЗначений[сч];
3. Степной 21 07.04.21 18:41 Сейчас в теме
(1) Еще вариант: загрузить ТЗ во временную таблицу, отфильтровать, выгрузить ТЗ.
7. nomad_irk 55 07.04.21 19:16 Сейчас в теме
(3)Зачем что-то куда-то выгружать, если коллекция имеет все методы для фильтрации?
Fox-trot; +1 Ответить
4. sergqwert15 2 07.04.21 18:47 Сейчас в теме
Можно сделать так?

ТаблицаЗначений.Индексы.Добавить("Количество");
МассивСтрок = ТаблицаЗначений.НайтиСтроки(Новый Структура("Количество",0));
Для Каждого Стр из массивСтрок Цикл
ТаблицаЗначений.Удалить(Стр)
КонецЦикла;
victorree; +1 Ответить
5. VictorRGB2 13 07.04.21 18:54 Сейчас в теме
(4) вам что хочется в итоге получить?
туже самую таблицу, только без Количество = 0?
если посмотреть внимательно на ваш цикл, то после первого же удаления строки, индексы в таблице сменятся и уже второе удаление удалить не ту строку, что надо
FatPanzer; +1 Ответить
6. spacecraft 07.04.21 18:55 Сейчас в теме
8. Aitbay 07.04.21 20:22 Сейчас в теме
если таблица большая можно ее передать параметром в зарос
и там по условию выбрать необходимые элементы
11. nomad_irk 55 08.04.21 07:10 Сейчас в теме
(8)с большой таблицей точно не стОит так делать, а с маленькой - тем более.
12. UtSpar 119 08.04.21 07:26 Сейчас в теме
(11)

А почему можете пояснить?

Тоже хотел такой вариант предложить - потом увидел ваш коммент.
14. nomad_irk 55 08.04.21 07:46 Сейчас в теме
(12)Потому что таблицу нужно передать в сторону сервера SQL, дождаться пока он из этой таблицы сделает временную таблицу, выделит ресурсы под индексы, обработает таблицу запросом с условием и вернет результат обратно.
Это все занимает время.

Существующая коллекция в виде ТЗ уже находится в ОЗУ сервера 1С и имеет собственные методы для фильтрации. Если существующих методов фильтрации ТЗ не хватает, то с помощью цикла реализуется нужный.
15. UtSpar 119 08.04.21 08:11 Сейчас в теме
(14) То есть независимо от объема, обработка на сервере в ОЗУ таблицы всегда быстрее чем ее перенос обработка и обратный перенос.

хммм, ну вроде логично все, спасибо)
16. FatPanzer 13 08.04.21 09:18 Сейчас в теме
(8) Чем вам так СУБД насолила, что вы хотите заставить её делать несвойственные вещи?
13. UtSpar 119 08.04.21 07:27 Сейчас в теме
У нас в тестовом задании для программиста есть задача по удалению строк из таблицы по условию.

В основном делают:
1. Запросом - таблицу в запрос, там в отбор - выгрузка.
2. Обратном перебором.
3. Сбором ссылок удаляемых строк в массив .удаление строк.
17. FatPanzer 13 08.04.21 09:19 Сейчас в теме
(13) На работу таких не брать.
20. SlavaKron 08.04.21 09:47 Сейчас в теме
Коллеги совсем забыли про СКД. Создаем схему СКД на основе набора-объект. В качестве внешнего набора подставляем нашу ТЗ. Создаем нужный отбор. Выгружаем результат СКД в коллекцию...
nomad_irk; FatPanzer; +2 Ответить
21. Степной 21 08.04.21 10:50 Сейчас в теме
(7) Это вариант для сложной фильтрации, например, с обращением к полям через точку для установки условия. А так, если рассматривать примитивное условие на "Количество = 0", то конечно, вариант с запросом на больших объемах данных проиграет.

И уж, если мы говорим о конкретной задаче и принимаем в качестве условия, что какие-то строки не нужны для дальнейшей работы, то, в первую очередь, нужно посмотреть на реализацию алгоритма их получения, и, если это возможно, в принципе не добавлять их в ТЗ.
22. nomad_irk 55 08.04.21 10:59 Сейчас в теме
(21)В задаче предельно ясно описан код. Из кода, думаю, большинству ясно, что никаких "мудреных" фильтраций не нужно.
Зачем придумывать условия задачи и потом успешно решать задачу в этих придуманных условиях?
23. Степной 21 08.04.21 11:14 Сейчас в теме
(22) Отвечая на вопросы на форуме, я обычно стараюсь, дать ответ, который может выходить за рамки вопроса. Так делаю, потому что допускаю, что другие специалисты, преимущественно начинающие, могут искать подобный кейс, но со своими нюансами.

Мне нравится обсуждение этого вопроса, здесь можно понять какие есть варианты в принципе (не исчерпывающие конечно), какие нужно использовать в конкретном кейсе, какие в более сложном.
24. starik-2005 2292 08.04.21 12:08 Сейчас в теме
Хороший код в (0), минимальное количество операций и дополнительных переменных. Все остальные варианты будут избыточными и смысл в них только для красоты:
Для Каждого Ст ИЗ Таблица.НайтиСтроки( Новый Структура("Количество", 0) ) Цикл
  Таблица.Удалить( Ст );
КонецЦикла; 
Да, строк меньше, код лаконичнее, но, думаю, то же самое время займет и ресурсы.
33. SlavaKron 08.04.21 14:05 Сейчас в теме
Немного тестов:
Удаление перебором: 203
Удаление через НайтиСтроки: 109
Удаление запросом: 203
Удаление обратным условием: 515
Некорректный тест – в запрос должна быть загружена вся ТЗ целиком.
37. starik-2005 2292 08.04.21 14:33 Сейчас в теме
(33)
ление через НайтиСтроки: 10
Думаю, что если не выделять отдельный массив (в цикле итерируемый список итак рассчитывается однократно) и записать все в одну строку, как Вы сделали для других методов, можно и ускорить чуток.
38. starik-2005 2292 08.04.21 14:36 Сейчас в теме
(33) ну и проблема в том, что для каждого метода у Вас генерируется разная таблица (количество удаляемых строк неодинаково).
40. SlavaKron 08.04.21 14:42 Сейчас в теме
(38) Если проверять общим тестом, то одна.
41. starik-2005 2292 08.04.21 14:43 Сейчас в теме
(40) Да, одна. Не сразу посмотрел на код общего теста.
39. SlavaKron 08.04.21 14:41 Сейчас в теме
Подправил тест:
Удаление запросом: 3 218
Удаление перебором: 219
Удаление через НайтиСтроки: 109
Удаление обратным условием: 531
Прикрепленные файлы:
ТестОбработкиТаблицыЗначений.epf
42. starik-2005 2292 08.04.21 14:45 Сейчас в теме
(39) в общем в минимализмах вариант не самый быстрый оказался, а самый банальный вариант оказался быстрее всего )))

Но вообще думаю, что стоит замерить каждый метод на чувствительность к количеству удаляемых строк. Сейчас в тесте 10% строк, которые подлежат удалению. Что произойдет, если количество строк вырастет до 90%?
43. starik-2005 2292 08.04.21 14:48 Сейчас в теме
(39) вот при 50% - уже запрос работает эффективнее:

Удаление перебором: 562
Удаление через НайтиСтроки: 468
Удаление запросом: 250
Удаление обратным условием: 500
44. SlavaKron 08.04.21 14:51 Сейчас в теме
(43)
Удаление запросом: 250
Есть предположение, что структура темп таблицы кешируется после первого запроса. Во всяком случае, последующие тесты с запросом выдают относительное время лучше, чем первый раз.
45. starik-2005 2292 08.04.21 14:54 Сейчас в теме
(44) перезашел в 1С, отключил отладку:
Удаление перебором: 578
Удаление через НайтиСтроки: 484
Удаление запросом: 235
Удаление обратным условием: 453


2-й раз:
Удаление обратным условием: 468
Удаление запросом: 234
Удаление через НайтиСтроки: 485
Удаление перебором: 594

	Запрос = Новый Запрос(
	"ВЫБРАТЬ
	|	ТЗ.Количество КАК Количество
	|ПОМЕСТИТЬ ВТ
	|ИЗ
	|	&ТЗ КАК ТЗ
	|;
	|
	|////////////////////////////////////////////////////////////­////////////////////
	|ВЫБРАТЬ
	|	*
	|ИЗ
	|	ВТ КАК ВТ
	|ГДЕ
	|	ВТ.Количество > 0");
	
	Запрос.УстановитьПараметр("ТЗ", ТЗ);
	
	ТЗ = Запрос.Выполнить().Выгрузить();
Показать
46. SlavaKron 08.04.21 14:56 Сейчас в теме
(45) Это странно. У меня клиент-сервер, без отладки, чистая конфигурация. После перезапуска при 50%:
Удаление перебором: 391
Удаление через НайтиСтроки: 375
Удаление запросом: 2 703
Удаление обратным условием: 375
47. starik-2005 2292 08.04.21 14:56 Сейчас в теме
(46)
Удаление запросом: 2 703
Так у Вас через SQL, а у меня файловая.
48. SlavaKron 08.04.21 14:59 Сейчас в теме
(47) Это не должно играть существенной роли, вы видимо проверяете той версией обработки, которая не всю таблицу отправляет в запрос:
&НаСервереБезКонтекста
Процедура УдалениеЗапросомНаСервере(Знач ТЗ = Неопределено)
	
	Если ТЗ = Неопределено Тогда
		ТЗ = СформироватьТаблицуЗначений();
	КонецЕсли;
	
	ОтметкаВремени = ТекущаяУниверсальнаяДатаВМиллисекундах();
	
	ТекстПолей = "";
	Для Каждого Колонка Из ТЗ.Колонки Цикл
		Если ТекстПолей = "" Тогда
			ТекстПолей = "ТЗ." + Колонка.Имя + " КАК " + Колонка.Имя;
		Иначе
			ТекстПолей = ТекстПолей + ", ТЗ." + Колонка.Имя + " КАК " + Колонка.Имя;
		КонецЕсли;
	КонецЦикла;
	
	ТекстЗапроса = "ВЫБРАТЬ " + ТекстПолей + " ПОМЕСТИТЬ ВТ ИЗ &ТЗ КАК ТЗ;";
	
	Запрос = Новый Запрос;
	
	Запрос.Текст = ТекстЗапроса +
	"ВЫБРАТЬ
	|	*
	|ИЗ
	|	ВТ КАК ВТ
	|ГДЕ
	|	ВТ.Количество > 0";
	
	Запрос.УстановитьПараметр("ТЗ", ТЗ);
	
	ТЗ = Запрос.Выполнить().Выгрузить();
	
	ВремяВыполнения = ТекущаяУниверсальнаяДатаВМиллисекундах() - ОтметкаВремени;
	
	Сообщить("Удаление запросом: " + ВремяВыполнения);
	
КонецПроцедуры
Показать
49. starik-2005 2292 08.04.21 15:01 Сейчас в теме
(48) да, действительно если просто "*" поставить в ВТ, то все приобретает иной оборот (думал, что у Вас там * и так стоит, не предполагал даже, что Вы так с полями извращаться будете)))))

Удаление перебором: 578
Удаление через НайтиСтроки: 484
Удаление запросом: 1 759
Удаление обратным условием: 500


	Запрос = Новый Запрос(
	"ВЫБРАТЬ
	|	*
	|ПОМЕСТИТЬ ВТ
	|ИЗ
	|	&ТЗ КАК ТЗ
	|;
	|
	|////////////////////////////////////////////////////////////­////////////////////
	|ВЫБРАТЬ
	|	*
	|ИЗ
	|	ВТ КАК ВТ
	|ГДЕ
	|	ВТ.Количество > 0");
Показать
SlavaKron; +1 Ответить
50. SlavaKron 08.04.21 15:08 Сейчас в теме
(49)
"ВЫБРАТЬ
| *
|ПОМЕСТИТЬ ВТ
|ИЗ
| &ТЗ КАК ТЗ
Почему-то думал, что для ТЗ это не сработает.
51. starik-2005 2292 08.04.21 15:09 Сейчас в теме
(50) просто конструктор не откроется. Я сто лет уже запрос без конструктора пишу - в нем только проверяю синтаксис.
52. herfis 408 12.04.21 09:32 Сейчас в теме
А если так?
ТЗ = ТЗ.Скопировать(ТЗ.НайтиСтроки(Отбор));
53. SlavaKron 12.04.21 09:42 Сейчас в теме
(52) Это вариант из (31). Он требует создание и заполнение колонки, поэтому немного проигрывает основному варианту через НайтиСтроки.
Оставьте свое сообщение
Вопросы с вознаграждением