Код разработчика в зависимости от опыта работы
Разработка - Рефакторинг и качество кода
(НЕ)много воды
Это пятничный пост, созданный шутки ради. В прошлый раз мы изучали "хардкод" про регистры бухгалтерии. Сегодня же будет простая тема. Вы не найдете здесь никакой полезной информации. Разве что ловкий ход при работе со SQL Server в конце статьи, но он вряд ли будет новостью для многих.
Сегодня мы на простой задаче рассмотрим как меняется код разработчика в зависимости от его опыта работы: как конкретно с платформой 1С:Предприятие, так и просто в роли разработчика. Опыт работы - это не размер стажа в трудовой книжке, а совокупность навыков, приобретенных в процессе решения задач. Поэтому стадии опыта разделим на такие уровни как:
- Начинающий (Junior)

- Уже с опытом (Middle)
- Ведущий разработчик (Senior)
- Эксперт (Expert)
- Огромный опыт (Oldschool)
Последний уровень особый и далее Вы узнаете почему.
Все что Вы увидите ниже будет в рамках кода встроенного языка платформы и немного SQL Server. Да, да! Мы чуть-чуть выйдем за рамки "желтой" экосистемы.
Задача
Вы же знаете, что за справочник "Номенклатура"? Не сомневаюсь! Он есть в большинстве прикладных решений на платформе 1С и содержит список номенклатурных позиций для ведения управленческого, регламентированного и любых других видов учета. В нем есть разнообразные настройки и большой объем связанного функционала (присоединение файлов, печатные формы и др.). Но мы, конечно же, обо всем этом говорить не будем.
Наша задача куда более простая - подсчитать количество элементов справочника "Номенклатура" в информационной базе. Что потом будет с полученным результатом подсчета нас не интересует. То есть фактически, мы реализуем функцию для решения этой задачи в общем модуле конфигурации. Все, никаких подвохов! Что же может такого случиться?
Вот и решения
Пойдем от простого к сложному с неожиданной концовкой.
Начинающий (Junior)
Для начинающего разработчика такое решение может показаться простым и правильным.
Функция ПолучитьКоличествоНоменклатуры() Экспорт
КоличествоЭлементов = 0;
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
КоличествоЭлементов = КоличествоЭлементов + 1;
КонецЦикла;
Возврат КоличествоЭлементов;
КонецФункции
Плюсы:
- Простое и понятное решение
Минусы:
- Низкая производительность
- Сложность в доработке / адаптации под новые требования
А Вы когда-нибудь такое делали? Я да! :)
Уже с опытом (Middle)
Спустя некоторое время разработчик открывает для себя запросы, и мы получаем следующий код.
// Количество элементов в справочнике "Номенклатура"
//
// Возвращаемое значение:
// - Число - количество найденных элементов.
//
Функция ПолучитьКоличествоНоменклатуры() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(Номенклатура.Ссылка) КАК КоличествоЭлементов
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
ВыборкаДетальныеЗаписи.Следующий();
КоличествоЭлементов = ВыборкаДетальныеЗаписи.КоличествоЭлементов;
Возврат КоличествоЭлементов;
КонецФункции
Плюсы:
- Эффективный подсчет количества записей запросом по сравнению с объектной моделью
- Легкая доработка / адаптация под новые требования
- Простое и понятное решение
Минусы:
- Производительность намного лучше предыдущего варианта, но все же для подсчета количества записей выполняется сканирование кластерного индекса. Частое выполнение такого запроса отрицательно сказывается на работе информационной системы.
Решение выглядит не плохо. Можно ли его улучшить?
Ведущий разработчик (Senior)
Спустя некоторое время разработчик получает еще порцию опыта, все больше втягивается в стандарты разработки, а также решает кэшировать количество записей для их эффективного получения.
#Область ПрограммныйИнтерфейс
// Количество элементов в справочнике "Номенклатура" из кэша
// в базе данных.
//
// Возвращаемое значение:
// - Число - количество найденных элементов.
//
Функция КоличествоНоменклатуры() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| КэшПоказателейДляОтчетности.КоличествоЭлементов КАК КоличествоЭлементов
|ИЗ
| РегистрСведений.КэшПоказателейДляОтчетности.СрезПоследних(, ПоказательДляОтчетности = &ПоказательДляОтчетности) КАК КэшПоказателейДляОтчетности";
Запрос.УстановитьПараметр("ПоказательДляОтчетности", Справочники.ПоказателиДляОтчетности.КоличествоНоменклатуры);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
КоличествоЭлементов = 0;
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
КоличествоЭлементов = ВыборкаДетальныеЗаписи.КоличествоЭлементов;
КонецЕсли;
Возврат КоличествоЭлементов;
КонецФункции
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейс
// Количество элементов в справочнике "Номенклатура"
//
// Возвращаемое значение:
// - Число - количество найденных элементов.
//
Функция КоличествоНоменклатурыСлужебный() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| КОЛИЧЕСТВО(Номенклатура.Ссылка) КАК КоличествоЭлементов
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
ВыборкаДетальныеЗаписи.Следующий();
КоличествоЭлементов = ВыборкаДетальныеЗаписи.КоличествоЭлементов;
Возврат КоличествоЭлементов;
КонецФункции
// Обработчик регламентного задания "Обновить кэш количества номенклатуры"
//
Процедура ОбновитьКэшКоличестваНоменклатуры() Экспорт
МетаданныеЗадания = Метаданные.РегламентныеЗадания.ОбновитьКэшКоличестваНоменклатуры;
ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания(МетаданныеЗадания);
НачатьТранзакцию();
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.КэшПоказателейДляОтчетности");
ЭлементБлокировки.УстановитьЗначение("ПоказательДляОтчетности", Справочники.ПоказателиДляОтчетности.КоличествоНоменклатуры);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();
Запись = РегистрыСведений.КэшПоказателейДляОтчетности.СоздатьМенеджерЗаписи();
Запись.Период = ТекущаяДатаСеанса();
Запись.ПоказательДляОтчетности = Справочники.ПоказателиДляОтчетности.КоличествоНоменклатуры;
Запись.КоличествоЭлементов = КоличествоНоменклатурыСлужебный();
Запись.Записать();
ЗафиксироватьТранзакцию();
КонецПроцедуры
#КонецОбласти
Как мы видим, теперь значения кэшируются в периодическом регистре сведений "Кэш показателей для отчетности". Обновление значения происходит регламентным заданием "Обновить кэш количества номенклатуры" с произвольным расписанием.
Плюсы:
- Максимальная производительность при получении количества записей
- Расширенные возможности по хранению историчности значения
Минусы:
- По сравнению с предыдущими решениями код выглядит значительно сложнее
- Не смотря на кэширование, все же требуется сканирование кластерного индекса для подсчета количества записей
- Присутствует некоторая неточность в данных, т.к. требуется постоянное обновление кэша регламентным заданием с некоторым "лагом" по времени
Ради оптимизации решение было усложнено, но недостаток в виде сканирования кластерного индекса все же остается.
Эксперт (Expert)
Но что, если и это нас не устраивает и нам нужно еще оптимизировать получение количества записей. Нужно больше оптимизаций!
#Область ПрограммныйИнтерфейс
// Количество элементов в справочнике "Номенклатура" из собранной статистики СУБД.
//
// Возвращаемое значение:
// - Число - количество найденных элементов.
//
Функция КоличествоНоменклатуры() Экспорт
КоличествоЭлементов = Неопределено;
МетаданныеТаблицы = Метаданные.Справочники.Номенклатура;
МассивМетаданных = Новый Массив;
МассивМетаданных.Добавить(МетаданныеТаблицы);
ИнформацияОСтруктуреБазы = ПолучитьСтруктуруХраненияБазыДанных(МассивМетаданных, Истина);
НайденныеТаблицы = ИнформацияОСтруктуреБазы.НайтиСтроки(Новый Структура("Назначение", "Основная"));
Если НайденныеТаблицы.Количество() = 1 Тогда
ИнформацияОТаблице = НайденныеТаблицы.Получить(0);
ИмяТаблицыБазыДанных = ИнформацияОТаблице.ИмяТаблицыХранения;
СтрокаПодключения = СтрокаПодключенияКБазеДанных();
СоединениеСБазой = СоздатьСоединениеСБазой(СтрокаПодключения);
Если НЕ СоединениеСБазой = Неопределено Тогда
Попытка
ТекстЗапроса = ТекстЗапросаКоличествоЗаписейНоменклатуры();
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "{TableName}", ИмяТаблицыБазыДанных);
КомандаБД = Новый COMОбъект("ADODB.Command");
КомандаБД.ActiveConnection = СоединениеСБазой;
КомандаБД.CommandText = ТекстЗапроса;
КомандаБД.CommandTimeout = 60;
РезультатБД = КомандаБД.Execute();
Пока НЕ РезультатБД.eof() Цикл
КоличествоЭлементов = РезультатБД.Fields.Item("rows").Value;
РезультатБД.MoveNext();
КонецЦикла;
Исключение
КоличествоЭлементов = Неопределено;
КонецПопытки;
КомандаБД = Неопределено;
СоединениеСБазой = Неопределено;
КонецЕсли;
КонецЕсли;
Если КоличествоЭлементов = Неопределено Тогда
КоличествоЭлементов = КоличествоНоменклатурыСлужебный();
КонецЕсли;
Возврат КоличествоЭлементов;
КонецФункции
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейс
// Количество элементов в справочнике "Номенклатура"
//
// Возвращаемое значение:
// - Число - количество найденных элементов.
//
Функция КоличествоНоменклатурыСлужебный() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| КОЛИЧЕСТВО(Номенклатура.Ссылка) КАК КоличествоЭлементов
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
ВыборкаДетальныеЗаписи.Следующий();
КоличествоЭлементов = ВыборкаДетальныеЗаписи.КоличествоЭлементов;
Возврат КоличествоЭлементов;
КонецФункции
// Сохранить строку подключения базы данных
//
// Параметры:
// СтрокаПодключения - Строка - Строка подключения к базе данных
//
Процедура СохранитьСтрокуПодключенияБазыДанных(СтрокаПодключения) Экспорт
ХранилищеОбщихНастроек.Сохранить(
"БазаДанных",
"СтрокаПодключения",
СтрокаПодключения,,
"DatabaseAdmin");
КонецПроцедуры
// Строка подключения к базе данных
//
// Возвращаемое значение:
// - Строка - Строка подключения к базе данных
//
Функция СтрокаПодключенияКБазеДанных() Экспорт
Возврат ХранилищеОбщихНастроек.Загрузить(
"БазаДанных",
"СтрокаПодключения",,
"DatabaseAdmin");
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция СоздатьСоединениеСБазой(СтрокаСоединения)
Соединение = Новый COMОбъект("ADODB.Connection");
Попытка
Соединение.Open(СтрокаСоединения);
Возврат Соединение;
Исключение
Соединение = Неопределено;
СообщениеОбОшибке =
"Ошибка установки соединения: "
+ Символы.ПС
+ ОписаниеОшибки();
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(СообщениеОбОшибке);
Возврат Неопределено;
КонецПопытки;
КонецФункции
Функция ТекстЗапросаКоличествоЗаписейНоменклатуры()
ТекстЗапроса =
"DECLARE @tableName sysname = '{TableName}'
|
|SELECT
| a2.name AS [table_name],
| a1.rows as [rows]
|FROM
| (SELECT
| ps.object_id,
| SUM (
| CASE
| WHEN (ps.index_id < 2) THEN row_count
| ELSE 0
| END
| ) AS [rows],
| SUM (ps.reserved_page_count) AS reserved,
| SUM (
| CASE
| WHEN (ps.index_id < 2) THEN (ps.in_row_data_page_count + ps.lob_used_page_count + ps.row_overflow_used_page_count)
| ELSE (ps.lob_used_page_count + ps.row_overflow_used_page_count)
| END
| ) AS data,
| SUM (ps.used_page_count) AS used
| FROM sys.dm_db_partition_stats ps
| GROUP BY ps.object_id) AS a1
| INNER JOIN sys.all_objects a2 ON ( a1.object_id = a2.object_id )
|WHERE a2.type <> N'S'
| and a2.type <> N'IT'
| and a2.name = @tableName";
Возврат ТекстЗапроса;
КонецФункции
#КонецОбласти
На этот раз была применена радикальная оптимизация: для получения количества записей в таблице используется собранная статистика SQL Server, которую СУБД обновляет достаточно оперативно. Чтобы такой подход заработал, придется выполнять SQL-запрос напрямую к базе данных с помощью ADO. Подробнее о реализации смотрите в листинге выше.
Плюсы:
- Максимальная производительность при получении количества записей таблицы.
Минусы:
- Сложное решение в части разработки и сопровождения
- Могут быть незначительные отклонения значения от фактического количества записей на короткий промежуток времени
Фактически, это самое сложное решение как в части разработки, так и в части сопровождения, но зато с максимальной эффективностью.
Огромный опыт (Oldschool)
А теперь представим, что у разработчика огромный опыт с разными версиями платформы 1С, за плечами множество внедрений и успешных проектов. Какое решение в такой ситуации будет реализовано?
Функция КоличествоНоменклатуры() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(Номенклатура.Ссылка) КАК КоличествоЭлементов
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
ВыборкаДетальныеЗаписи.Следующий();
КоличествоЭлементов = ВыборкаДетальныеЗаписи.КоличествоЭлементов;
Возврат КоличествоЭлементов;
КонецФункции
Правильно - самое эффективное с точки зрения простоты разработки и скорости работы. Ведь все мы знаем, что предварительные оптимизации - зло.
Весело?
С пятницей, коллеги (если Вы читаете это в пятницу)! И хорошего дня в любом случае.
Мы рассмотрели пять решений одной простой задачи. Как мы видим, даже простейшая задача может быть усложнена в несколько раз и использовать нестандартные подходы при реализации. Чем больше опыта у разработчика, тем сложнее задачи он может решать. Но есть и другая сторона - простые задачи в таких случаях могут решаться слишком сложными способами, которые не всегда обоснованы.
Думаю, если проследите за изменением кода, то все встанет на свои места.
А как бы Вы решали подобную задачу?
Авторские разработки
-
Транслятор запросов 1С в SQL - инструмент для трансляции запросов платформы 1С в SQL, а также их диагностики.
-
Помощник работы с идентификаторами объектов - инструмент для расширенного анализа идентификаторов объектов.
-
Анализ производительности APDEX - отчет для просмотра и анализа замеров производительности в конфигурациях на базе БСП.
-
Путеводитель по истории релизов - отчет по истории выпуска релизов продуктов фирмы "1С" и анализа информации по обновлениям.
-
Просмотр и анализ структуры базы данных (отчет на СКД) - отчет для просмотра и анализа структуры базы данных с поддержкой файловых баз (ограниченный режим), а также баз на SQL Server и PostgreSQL.
-
Просмотр и анализ журнала регистрации (отчет на СКД) - отчет на базе системы компоновки данных (СКД) для просмотра записей журнала регистрации.
-
Обозреватель криптографии - отчет для просмотра доступных провайдеров и сертификатов криптографии на сервере и клиенте.
-
Пакетная выгрузка / загрузка внешних отчетов и обработок - пакетная выгрузка / загрузка внешних отчетов и обработок для массовый манипуляций с ними.
-
Мастер полнотекстового поиска - набор инструментов для работы с полнотекстовым индексом платформы 1С. Стандартные и расширенные возможности.
-
Командный интерпретатор для 1С - инструмент для выполнения команд CMD / PowerShell из 1С.
Вступайте в нашу телеграмм-группу Инфостарт
1С опыт разработчик разработка карьера качество оптимизация
Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
См. также
Нейросети Рефакторинг и качество кода Запросы Разработчик 1С 8.3 Абонемент ($m)
Нейросеть написала запрос или процедуру для вашей базы 1С, и непонятно, все ли имена в нём настоящие. Обработка компилирует текст без выполнения, сверяет его с метаданными этой базы и к каждой ошибке пишет настоящее имя, например ВНаличииОстаток вместо выдуманного КоличествоОстаток. Список ошибок с подсказками одной кнопкой копируется обратно в чат с моделью.
10 стартмани
02.11.2026 287 1 nedomolkov.ivan 1
Рефакторинг и качество кода Разработчик 1С:Предприятие 8 Россия Бесплатно (free)
Одна проверка в обработчике кнопки может выглядеть достаточной, пока ту же операцию не вызовут из другого места. На примере управляемой формы разберём, почему так происходит, как разместить проверку в общей серверной функции и чем отличается удобная проверка ввода от обязательного условия выполнения операции.
29.10.2026 324 YA_777378709 0
Рефакторинг и качество кода Разработчик Бесплатно (free)
Рассказываем, почему качественный код – это не техническая прихоть, а актив, который помогает бизнесу быстрее адаптироваться к изменениям и запускать новые фичи без бесконечного преодоления техдолга. Показываем, как объяснить бизнесу ценность рефакторинга через понятные признаки: замедление разработки, неточные оценки, страх перед legacy и хрупкость системы. Разбираем, почему неправильный рефакторинг может быть дороже его отсутствия, какие анти-паттерны ломают процесс и как не превратить улучшения в бесконечную переделку ради переделки. Объясняем, как сделать рефакторинг частью культуры команды: договориться с бизнесом, научить разработчиков видеть проблемные места, закрепить правила и поддерживать улучшения на уровне тимлидов, архитекторов и всей команды.
28.10.2026 430 Pavel791 0
Рефакторинг и качество кода HighLoad оптимизация Системный администратор Разработчик Стажер 1С 8.3 Абонемент ($m)
Если к HTTP-сервису 1С обращаются сразу несколько программ, сколько запросов в секунду он успеет обработать? Я опубликовала простой HTTP-сервис на нашей "подопытной" конфигурации «Нано-УТ» (файловая база, Apache, без прав администратора) и нагрузила его скриптом на Python. Ответ: около 15-16 запросов в секунду, сколько бы клиентов ни обращалось одновременно. Запросы ждут своей очереди, и при 32 клиентах ответ приходит через 2 секунды вместо 64 мс. Заодно разобрала скрипт из первого варианта статьи: он «проверял» сервер, который отвечал по одному, и считал ошибки вместе с успешными ответами. В архиве исправленный скрипт, учебный сервер, HTTP-сервис для 1С и инструкция по запуску.
1 стартмани
23.10.2026 485 Ninel_S 3
Рефакторинг и качество кода Разработчик 1С 8.3 Абонемент ($m)
Запустили Analyzer 1C 2.7.65 на промышленной конфигурации (596 модулей, 13 669 функций) и исследовали перегруженные функции (до 1887 строк), циклические зависимости и экран «Циклы» (кольцо из 64 модулей). Разобрали, почему популярные метрики (McCabe, связность) не представлены в продукте вендора, и составили пошаговый план разделения модуля. Привели проверенный платформой 8.3.27 пример до и после рефакторинга и выявили скрытую ловушку загрузки модулей с точкой в имени.
9 стартмани
19.10.2026 431 Ninel_S 2
Рефакторинг и качество кода EDT СКД Разработчик 1С 8.3 1С 8.5 1С:Бухгалтерия 3.0 Бесплатно (free)
Одиннадцать граблей схем компоновки, которые не видно в конструкторе и не ловит EDT, на реальных отчетах БП КОРП. Формат числа задается в двух местах, и условное оформление варианта перебивает формат поля. Ресурс складывает штуки с часами, и помогает выражение «только когда единица одна». Ресурс пуст в детальных записях, параметр не появляется в шапке без userSettingID, valueListAllowed ломает границы периода, Остатки и СрезПоследних с параметром периода падают с «Несоответствием типов», title без xsi:type дает «Исключение XDTO» при загрузке. В конце код проверки схемы из файла до обновления базы, сводная таблица и чеклист.
16.10.2026 469 Konstmax13 2
Инструментарий разработчика Нейросети Рефакторинг и качество кода EDT Разработчик 1С 8.3 1С 8.5 1С:Бухгалтерия 3.0 Бесплатно (free)
Как ИИ-агент (Claude Code) работает в живом EDT-проекте 1С:Бухгалтерии КОРП 3.0: из чего собрать стенд с MCP-сервером для EDT, как ставить задачи агенту, где он ломает проект и какие проверки это ловят. Реальные случаи: рукописные метаданные, ронявшие конфигуратор; четыре дня зависшего обновления из-за порядка блоков в Rights.rights; ошибки, которые EDT пропускает, а платформа нет; сплошная сверка вместо «вроде работает». В приложении шаблон CLAUDE.md, шаблон правила, чеклист перед обновлением базы и скрипты проверки ролей и схем СКД.
15.10.2026 3362 Konstmax13 11
Рефакторинг и качество кода Тестирование QA Разработчик 1С 8.3 Абонемент ($m)
Инженерный анализ влияния (Impact Analysis) при изменении общего метода в 1С:Предприятии: почему штатный поиск ссылок скрывает 99% зависимостей и как обратный обход графа вызовов выявляет 370 скрытых потребителей на глубине 3 уровней. В статье — верификация сквозной цепочки обмена с маркетплейсом; в архиве-компаньоне — автономный BFS-анализатор на Python, слепки графа и план регрессионного тестирования.
1 стартмани
12.10.2026 290 Ninel_S 0
-1 уровень ("да я в этой 1С уже пол года данные вбиваю, не посчитаю что ли"):
Итого=0;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.ссылка
| Сумма(1) КАК КоличествоЭлементов
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|СГРУППИРОВАТЬ ПО
|Номенклатура.Ссылка";
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
Для каждого строкаТЗ из РезультатЗапроса цикл
Итого=Итого+РезультатЗапроса.КоличествоЭлементов;
Конеццикла;
Возврат Итого; ПоказатьКоллеги, продолжайте)
ВЫБРАТЬ
КОЛИЧЕСТВО(0) КАК Элементов
ИЗ
Справочник.Номенклатураа лучше засунуть в экспортную функцию, куда передавать имя таблицы, чтоб код не повторять
и в привилегированном режиме, мало ли какие RLS'ы включены :-D
"ВЫБРАТЬ КОЛИЧЕСТВО(0) КАК Элементов ИЗ "+ИмяТаблицыв результате запроса на сервак всегда возвращается 1 число, а не целый список.
зачем? просто потому что можешь? в газенваген такого разработчика.
если Linux используется на сервере приложений 1С? я бы не стал использовать платформозависимые инструменты.
2) мля, кэш на список номенклатуры, вы поехавшие что-ли?
кэширование вызывает массу проблем - показатель надо вечно обновлять делая select count(1) from table.
и что опаснее - посмотреть 1 раз кол-во номенклатуры, или после каждой записи номенклатуры проверять ее количество?
по-моему такое делать надо тупо on request, то есть в отчете.
3) никто еще не сказал что
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
ВыборкаДетальныеЗаписи.Следующий();
КоличествоЭлементов = ВыборкаДетальныеЗаписи.КоличествоЭлементов;
если агрегационную функцию count сделать на пустом справочнике она вернет null, и что будет в количество элементов? null? тут просто без комментариев. 10-часовая версия видео про "лох-пидр"
Это сакральные знания! Потому что никто еще не видел пустых справочников "Номенклатура" в реальных компаниях )))
Добавить 2 подписки на события, хранить количество номенклатуры в служебном регистре или константе, при добавлении элемента прибавлять количество, а при удалении уменьшать. Сделать отключаемым, при массовой загрузке отключать и количество пересчитывать самостоятельно.
Вот это костыли я описал!
Идея о переносе затратного по времени процесса на отдельные операции идея правильная, но
есть варианты когда контрагенты могут появиться/исчезнуть в базе мимо вызова вашего кода который будет вести подсчет.
Поэтому мне больше всего нравится вариант с константой которая будет меняться в транзакции, или пусть даже ваш вариант с регистром, но при этом дополнительно должно вызываться регламентное задание по расписанию которое будет заполнять константу по запросу.
Все.
Но еще раз напоминаю, что тут нет контекста. Это шуточная статья ))))
Идем в БД. Городим у таблицы справочника собственный primary key, который будет равен guid + № п/п. Пишем триггер и хранимку, которая обеспечит его заполнение. Запрещаем удалять из справочника элементы, разрешаем только добавлять и помечать на удаление. Далее селект 1 сорт бай пр. кей аск.
Тоже самое можно будет и на 1С, через подписку и отдельный индексируемый реквизит № п/п
Наслаждайтесь
Не смог выполнить задачу!
Вспомнил еще уровень
Функция КоличествоНоменклатуры() Экспорт
Возврат 42;
КонецФункции
:))))))))
Не, так это норм еще...
Более продвинутый уровень:
Функция КоличествоНоменклатуры() Экспорт
Возврат ПолучитьСорокДва();
КонецФункции
Функция ПолучитьСорокДва()
Возврат 42;
КонецФункции
ПоказатьДвижение — всё, цель — ничто! (с)
Настоящий олдскул написал бы так:
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
Возврат ВыборкаДетальныеЗаписи.КоличествоЭлементов;
КонецЕсли;
Возврат 0;
А то мало ли что... :)
Так что кому-как, а мне очень-таки жизненный пример ;)
*пятница*
Для не очень быстрых как я поясню - выборка в ДАННОМ случае, при ТАКОМ запросе вернет всегда 1 строку, а не любая выборка из любого запроса...
Текст задачи:
"В базе работают 1000 пользователей. Есть регистр сведений в нем 100 млн записей. запрос select count выполняется t= 60 сек. Необходимо сделать так, чтобы данные были получены за t = 1c."
Можете ли Вы подсказать, пожалуйста, в каком направлении мыслить/искать? Преподаватель говорит, есть порядка 12 способов решить задачу.
могу предложить поискать решение по следующему алгоритму: разделить размер таблицы на размер записи.
Честно сказать, я не ожидал такой бурной реакции. Я хотел показать, что часто при росте от джуна до сеньора разработчики используют фичи которые им интересны, но без которых можно было бы решить задачу проще и быстрее. Но интерес делает свое дело и решения в угоду творчеству и экспериментов значительно усложняется. Это не плохо, даже хорошо, но в меру.
Опытные же разработчики, которые весь этот путь уже прошли, решают задачу самым простым и быстрым способом, если этого не требуют другие условия.
Всем добра, кто прочитает этот комментарий :)
Чем меньше токсичности в ИТ, тем лучше! )))
КолВоТвары = Даша.ОтветНаВопрос("Але гараж, скока у нас номклатур - быра посчитай");
и это будет самое оптимальное решение и не важно как она там посчитает.
ломовая лошадь, которая тянет все.
сейчас на практике нужна не старая лошадь, а умение быстро и надежно объездить молодого жеребца
или обломать рога горной лани. но когда клиент просит ковбоя это сделать, то он предлагает
свою клячу-медалистку и потом слышим лепет... не успели, отложили, закрыли.
&НаСервереБезКонтекста
Функция КолвоНоменклатуры()
Текст = "ВЫБРАТЬ
| Номенклатура.Код КАК Код
|ИЗ
| Справочник.Номенклатура КАК Номенклатура"
;
Запрос = Новый Запрос;
Запрос.Текст = Текст;
Возврат Запрос.Выполнить().Выгрузить().Количество();
КонецФункции
ПоказатьТекст = "ВЫБРАТЬ
| ВЫРАЗИТЬ(Номенклатура.Код КАК Строка(1)) КАК Код
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";Так еще оптмальней :)
Не знаю как у мелкософта , но на postgresql конструкция типа sel ect count(*) fr om ... тяжело работает. Проще к статистике обратиться Плюс-минус лапоть узнаешь количество записей в таблице
вы серьезно думаете что перебросить миллионы записей на клиента, загрузить их в таблицу значений, после чего посчитать быстрее чем sel ect count(*) fr om на сервере??? Вы так шутить изволите?
Умещать логику в одну строку, мысль правильная, но "Возврат Запрос.Выполнить().Выгрузить().Количество();" - это лютый быдлокод)
Далеко еще до олда, вот так правильно: "Возврат Запрос.Выполнить().Выгрузить()[0].КоличествоЭлементов" (не меняя изначального запроса и игноря пустоту)
В 2000 разовом цикле 8 секунд против 6 минут на 70 000 элементах)
Прозевал Вашу реплику... Отвечу так. Истинный ТРУ Олдскул знает о чем Вы говорите. Но Метод Вами предложенный конечно дает выигрыш по времени извлечения результат (1690 ms), но гораздо затратней по ресурсам. И в хост ничего не сосется :) На клиент возвращается примитивное значение. А что творится в рамках кластера, олдскульного 1С-нига не должно интересовать. Бикоз, если одноэсниг начнет разбираться а что же там на самом деле происходит, он быстро соскочит на ДОТ.НЕТ например.
Текст запроса |
|---|
лТекст = "
|ВЫБРАТЬ первые 1000000
| Числа.Период КАК Период,
| Числа.Число1 КАК Число1,
| Числа.Число2 КАК Число2,
| Числа.Число3 КАК Число3
|ИЗ
| РегистрСведений.Числа КАК Числа
|";
лЗапрос = Новый Запрос(лТекст);
Сообщить(ТекущаяДата());
лВыборка = лЗапрос.Выполнить().Выгрузить().Количество();
Сообщить(ТекущаяДата());
лВыборка = лЗапрос.Выполнить().Выбрать().Количество();
Показать |
Сюда положил счетчики оборудования, если кому интересно. Смотреть %Загруженности процессора и байт исключительного пользования rphost1800
Интересная статистика получилась, никогда не мог бы подумать, что экономя память приходится жертвовать процессором. Может кто из экспертов подскажет.
17.02.2020 21:58:20 Выгрузить().
17.02.2020 21:58:34 Выбрать()
П.С. Виртуалка не настроена и используется как временная песочница и дал я ей только 3 ядра, чтобы на оставшемся смотреть котиков в интернете.
Спасибо за проделанную работу!
В заключение пятничного флейма... Не могу согласится с мнением коллег, что длина стажа не имеет значения. Когда 20 лет помедитируешь на творение 1С , аж с самого основания, такие нюансы начинаешь спинным мозгом чувствовать, без всяких рекомендаций от 1С. Даже если и отстаешь от модных фишек платформы. И не всегда, ТО, чему учат в УЦ, нужно слепо применять на проектах в виде гуд практикс
Железо I7-2600 4 физических ядра, память 16 гектар, сервер 1С и Постгрес 9,2 #изкаропки. Ничего не тюнил. ОС Центос - 7
Запрос ВремяИсполнения Загрузка rpHost Загрузка PostgreSQL
#1 485ms 10% 96%
#2 2464ms 15% 47%
#3 2393ms 34% 48%
Где Запрос #1 - олдскульный от автора
Запросы #2 и #3 - ТРУ олдскульные... можно даже сказать ЛАМПОВЫЕ от меня ... сейчас объясню почему.
Не смотря на то что результат запроса #2 был получен за 2464мс (5раз медленней чем #1), были сэкономлены ресурсы сервера для других
,более важных операций. Экстаполируйте такие ситуации на продакшен эксплуатацию системы. Когда Вы побежите за новым железом ? :)
Замеры средние, каждая выборка по 10 раз. Расход оперативы 25% во всех случаях. Даже не шелохнулось.
Вывод - хоть и пятничная тема, но следует задуматься за счет чего делается оптимизация и нужна ли она повсеместно. За все приходится платить. Или временем или деньгами на гонку вооружений.
На самом деле информативненько было посомтреть особенно, что относилось к АДО. Ну я с Вами могу поспорить конечно. Вы забыли о главном это какой же реально объем у справочника номенклатуры и какой у него прирост. Поэтому эффективность запроса у мидла вполне адекватная. Во-вторых я сомневаюсь, что эксперт такое бы городил огород с АДО! А с регистром кэшей тоже не так все сладко - его ведь надо еще и записать тем же самым раставить блокировки. Ну да конечно можно записывать в нерабочее время и бла-бла... Не ну однозначно я не говорю, что я эксперт но однозначно запрос 1с будет выигрывать не только в быстроте но и простоте своей значимости. Более того раз уж так хочется его можно разместить в кеш вызова повторного использования. Все зависит от прироста справоника. Это есть над чем поговорить - простая тема, а у дельных спецов я думаю вызовет массу споров. Вот меня заинтриговала Ваша позиция...
З.Ы. Забыл уточнить еще время соединения очень интригующая штука и тут вы с АДО можете проиграть! Выыгриш может и будет только надо понять на каком количестве позиций, а это зависит от многих факторов. Железа , загрузка системы, состояне и актуальнсть статистики . много факторов и каждый раз может же меняться. Так что я Уважаю я Вас как профессионала своего дела но все же как мне кажется это притянуто за уши. Извените если бросил камень в Ваш огород.
Моя позиция проста: решение должно быть рабочим и не усложнять жизнь сопровождению и разработке. Так что все эти решения имеют право на жизнь. Я бы поспорил только с решением джуна :)
Я человек простой - решаю задачи в зависимости от условий, архитектуры. А спорить о реализации - это холивар. Не ко мне :) Коллеги выше много наобсуждали, это к ним. Я бы выбрал простое решение.
Выше отвечал, продублирую здесь:
Честно сказать, я не ожидал такой бурной реакции. Я хотел показать, что часто при росте от джуна до сеньора разработчики используют фичи которые им интересны, но без которых можно было бы решить задачу проще и быстрее. Но интерес делает свое дело и решения в угоду творчеству и экспериментов значительно усложняется. Это не плохо, даже хорошо, но в меру.
Опытные же разработчики, которые весь этот путь уже прошли, решают задачу самым простым и быстрым способом, если этого не требуют другие условия. Но, в то же время, могут упустить новые возможности платформы, которые более эффективны старых походов.
Всем добра, кто прочитает этот комментарий :)
Чем меньше токсичности в ИТ, тем лучше! )))
В принципе партии-серии-договора-соглашения так и работают.
Вы можете своей статьей вводить новичков в заблуждение ) которые будут стремиться к усложнению и заморочкам, вместо простоты и чистоты. Комментарии не все читаю, просто на мой взгляд заголовок статьи и преподносимое содержимое, должно звучать по другому - как может меняться и далее в этом духе. В конце же, сделать заключение, что-то типа не стоит стремиться к вариантам типа кэширования и получения через статистику, поэтому и поэтому. Это мое мнение. Белокаменцева никто не оскорблял, вы так решили)
Я статью прочитал, пытаюсь объяснить вам свою точку зрения, попытаюсь еще раз:
Ваша градация по количеству опыту и принимаемому решению, это чисто ваша фантазия/видение, на деле, все может различаться, причем кардинально. некоторые программисты могут сразу понимать что к чему, кто-то так и писать такие задачи на уровне выборке. Варианты с кэшом и получением из БД, извиняюсь, чистая фантазия, очень удивлюсь, если встречу такие решения в жизни, должны быть весомые обоснования. Тоесть в вашем видении с опытом у человека меняется стиль кодирования, на каком-то уровне он заморачивается, а потом становится Буддой 1С, к сожалению это не так. Как-то пришлось проводить собеседование одного товарища, 10 лет опыта, дал задание на запрос, где участвовали перечисления, он обращался в перечислениях не по ЗНАЧЕНИЕ() а по Индексу или как там это поле в запросе. Все очень относительно, поэтому на мой взгляд, не стоит проводить такую градацию.
Это конечно, другая сфера, к статье относящаяся слабо, по разному оцениваются последствия. Дешевле или правильнее или интереснее или привычнее сделать другую базу той же УТ 11, где будет по характеристикам и с партнерами. Или обработками перекроить? Или новые приходы-расходы по другому вводить?
И после нескольких таких изменений могут попросить сформировать отчет за несколько лет.
АДО для таких случаев вполне адекватный выбор инструмента.
Это тоже уровни, но уже консультантов.
Почему бы не отдать все считать серверу SQL как самому производительному в нашей цепочке, при этом код остается доступным и понятным для поддерживания даже джунами.
&НаКлиенте
Процедура Посчитать(Команда)
ПосчитатьНаСервере();
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ПосчитатьНаСервере()
//{{КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
// Данный фрагмент построен конструктором.
// При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!!
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(Номенклатура.Ссылка) КАК Количество
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
// Вставить обработку выборки ВыборкаДетальныеЗаписи
Сообщить(ВыборкаДетальныеЗаписи.Количество);
КонецЦикла;
//}}КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
КонецПроцедуры ПоказатьПлохо смотрели... Я не поленился и все "олдскульные" способы проверил на 1005000 записей. По скорости извлечения результата победил Автор! Но на моей тестовой площадке PostgreSQL кратковременно уперся рогами в землю. Поэтому в выигрыше экспермент #2! Так как, не смотря на потерю скорости в 5 раз, были сэкономлены ресурсы сервера для других, не менее важных параллельных! запросов/транзакций :) Только истинные мастера думают о high_load. Но! Судя по Вашему кодингу - Вы настоящий ТРУ Олдскул... круче чем я, даже! Вы единственный, кто догадался заюзать конструктор запросов с обработкой результата.
Хорошего настроения до следующей пятницы. Может еще кто сможет нас развеселить :)
(142)
странно, будет под рукой сервер протестирую на скорость вариант 2 и мой.
Что же касательно конструктора, то тут пример, как написав одну строчку кода в кратчайшие сроки можно получить результат понятный и доступный для всех. Вот уж олдскулом тут пахнет мало))))))))))
Есть другая идея. Взять реальную задачу из ОУ и выполнить ее в самых жестких, с точки зрения оборудования, условиях. И критерием настоящего олдскульного решения будет минимальное время проведения на списание товара, при минимальном потреблении ресурсов процессора. На одном физическом ядре с оперативой в 4 gb. Тактовая частота процессора не имеет значения, потом апроксимируем на время при наличии нескольких решений. в качестве sql сервера - постгрес. Вот это будет веселуха! Могу подкинуть задачку из 1С-Специалист, доведенную до реальных боевых условий
Не ну если говорить о самых жестких условиях - то это файловая база)))))
И это, мне как то за всю деятельность ни разу не приходилось писать ОУ специалиста на реальных задачах. Зачастую проще предложить шо нить базовое и доработать.
А это ваабще высший пилотаж с точки зрения highload. Прикидываете, миллион пользователей посчитали вручную без взаимных блокировок и прочей мути. А олдскул сэкономил свое время на девочек и 10000$ на новый 32 ядерный проц
Не важно как пишут мамонты и папонты. Важно под что заточен человек который называет себя 1С девом. In my opinion, одноэсник должен эффективно решать задачи предметной области используя инструмент под названием платформа 1С. А все что связано с оптимизацией, индексами и прочей ерундой пусть занимается команда Нуралиева, если хочет устоять на рынке. Еще раз повторюсь, если одноэсник начнет разбираться со всеми потрохами что происходят "позади сцены" - он быстро придет к выводу что пора валить.
Ниче не понял, но звучит как то не айс.
Вообще команда Нуралиева - это лишь вершина айсберга. Каждый разраб 1С - есть ячейка судна общества Нуралиева, который непрерывно борется с косяками 1С - чтобы судно не затонуло
Вот это и есть главная проблема.
Вспоминается капитан Врунгель. Как вы яхту назовете, так она и поплывет
Давно уже 1с слезла с этой иглы и в 2020 году решать задачи методами 2001-2003 годов для эксперта - верх безграмотности.
Требую продолжение банкета! :))
Предлагаю Вам поддержать инициативу пенсионера в IT следующего содержания;
- Взять реальную задачу из ОУ и выполнить ее в самых жестких, с точки зрения оборудования, условиях. И критерием настоящего олдскульного решения будет минимальное время проведения на списание товара, при минимальном потреблении ресурсов процессора,памяти и т.д. На одном физическом ядре с оперативой в 4 gb. Тактовая частота процессора не имеет значения, потом апроксимируем на время при наличии нескольких решений.
В качестве sql сервера - постгрес. Вот это будет веселуха!
Могу подкинуть задачку из 1С-Специалист, доведенную до реальных боевых условий.
Файловая система не пойдет. Не те масштабы. Только PostgreSql - только хардкор ;)
Не забываем что мы думаем о highload на зачуханном железе 10 летней давности. Обычно, у подавляющего большинства клиентов такое стоит.
Ну вот... опять конфликт поколений! ;)) Тогда что-же по Вашему Highload, как если не возможность подключиться к кофемолке на 386SX процессоре с 640кб озу и MFM-овским винтом на 20Гб 10000 пользователям и осуществить одновременно, параллельно списание товара из регистра накопления?
Для меня Highload - это много пользователей, высокая нагрузка на все компоненты системы, мониторинг, большая чувствительность к ошибкам в части производительности.
Кофемолка -- ну это не высокая нагрузка. 10000 на кофемолке не взлетят, ядер не хватит))))
pS. Главное - это понимание что все старо как мир. Проблемы тогда и сейчас - одни и те-же. Технологические обертки разные, и не всегда то что СЕЙЧАС , эффективней чем то что было ТОГДА. Это философский вопрос.
Дилетантское мнение диванного эксперта. У нас на новых самолётах пилоты мало того что обучаются в специализированном учебном центре производителя, летать именно на конкретной модели, так ещё и пол года летают с инструктором имеющем большой налёт именно на этой модели.
Вы,мил человек, также далеки от авиации... как я от дивана. Позвольте полюбопытствовать, куда делась целая ватага пилотов гражданской авиации почившего в бозе Советского Союза, когда массово списывали Тушки, Яки и те же кукурузники? Пральна, часть из них пошло на переобучение. Только вот их путь к сертификации пилота по международным правилам был значительно короче и легче, чем нынешнего курсанта. Так шта... Вы не поняли главную мысль - Квалификацию или навык проще восстановить и прокачать на новую модель, нежели приобрести с нуля и прокачать. У старой гвардии (с опытом) однозначно это быстрей получиться.
Ага... далёк, через два стола от меня сидят....
Именно, переобучились и не за два дня... по этому говорить что каждый пилот кукурузника может управлять боингом это не более чем мнение диванного эксперта.
З.Ы. не всяких пилотов берут. Только тех которые летали на определённом классе самолётов. Это даже с условием переобучения.
Кто доверит пилоту "кукурузника" какой нибудь "гольфстрим" стоимостью 50+ млн долларов.
Функция КоличествоЭлементовСправочника(ИмяСправочника) Экспорт
Запрос = Новый Запрос(
СтрШаблон(
"ВЫБРАТЬ
| КОЛИЧЕСТВО(Т.Ссылка) КАК КоличествоЭлементов
|ИЗ
| Справочник.%1 КАК Т
|ГДЕ
| НЕ Т.ЭтоГруппа", ИмяСправочника));
Выборка = Запрос.Выполнить().Выбрать();
Выборка.Следующий();
Возврат Выборка.КоличествоЭлементов;
КонецФункции
ПоказатьНадо определиться: 1С это бизнес разработка, или всё же язык системного уровня?
плюс - зачем вообще создавать вероятность получения различных результатов в таком случае?
ведь от какого-нибудь дотошного манагера потом услышишь, что "ваша программа неправильно считает кол-во номенклатуры"
Эта DMV содержит внутренне состояние показателей сервера и обновляется мгновенно, практически в реальном времени. Приближенное значение может не соответствовать фактическому количеству записей в таблице при наличии активных транзакций, например. Но и обычный запрос из 1С изменения активный транзакций не учитывает в режиме RCSI.
Так о какой разнице все же идет речь?
я не разбираюсь в вопросе статистики MS SQL Server'а, поэтому не могу парировать. раз обновляется в реальном времени, то вариант годный, если не планируется Linux'а.
Но сам вариант решения конечно с большими минусами. Это и неплатформенные возможности, привязка к ADO, сложности сопровождения и настройки, т..к это потребует доп. знаний.
Для тиражных решений это точно не подойдет. Только для чего-то узкоспециализированного.
Так что решение не идеальное.
Статья была больше для шутки, как разработчики могут усложнять решения. Это же не реальный кейс.
Основная идея создания 1С была в том, чтобы сделать более дружелюбный инструмент разработки, доработки для бухгалтера. Потом туда нагнали программистов-оптимизаторов, которые выбросили все удобные конструкции залезли в SQL и сейчас выпендриваются не поделу. Если нужна скорость, производительность в вычислениях, то 1С точно плохой вариант. И любой разработчик не зашоренный пойдёт в другие языки, другие решения. А 1С разработчик с опытом, но нежеланием изучать что-то ещё, полезет оптимизировать то, что у него под рукой.
Это пожалуй одна из лучших наглядных и простых иллюстраций как разработчики меняются с опытом. И это не только в 1С но и в других языка. Основная же мысль в разработке заключается в том, что не важно на сколько эффективно работает ваш код, если его не сможет доработать другой программист, потому что магия происходящая весьма чудесна и не постижима для магов уровнем ниже Магистра.
У второго и третьего комы - днодна сразу видно что новечки и сыпанутся на линуксе с постгри - где насколько помню не хранится количество строк таблицы.
Первый просто новичок и не понимает что пишет, оптимальным и кроссплатформенным было бы при добавление новой или удаление сохранять значение в константу - мало кода, понятно и быстро.
Вы можете заказать платную консультацию или разработку у автора. Будет создан приватный заказ на «Бирже заказов» для автора.
№ 1195044
Создание 14.02.20 07:52
Обновление 14.02.20 07:52
Просмотры 20859
Загрузки 0
Рейтинг
107
Комментарии 231
Код открыт Да
Рубрики Рефакторинг и качество кода
Кому
Разработчик
,
Стажер
Тип файла Нет файла
Платформа 1С:Предприятие 8
Конфигурация Универсальные
Операционная система Не имеет значения
Страна Не имеет значения
Отрасль Не имеет значения
Налоги Не имеет значения
Вид учета Не имеет значения
Доступ к файлу Бесплатно (free)