Garry Lider январь 2003 Предлагаемые вашему вниманию мемуары посвящены проблеме замедления работы с формой списка, нагруженной
вычисляемыми колонками. В конце эссе автор приводит рецепт, который, по его словам, якобы может
снять упомянутое торможение.
События, описанные ниже разворачивались на:
База данных: 1C v7.70.015 for SQL, Оперативный учёт
Конфигурация: доморощенная, отдалённым предком которой являлась ТиС 8.0
Пользователей, работающих одновременно: ~30 чел. (в т.ч., интенсивно проводящих накладные ~15 чел.)
Сеть: витая пара, 100 Мегабит
Сервер: 2xPentium-III, RAM 2Gb, MS Windows 2000 Server, MS SQL 2000
Рабочие станции: 98/Ме/2k/ХР, CPU от 200 MHz, RAM от 32 Мb
В качестве характерного примера рассматривается форма списка справочника "Номенклатура".
В один прекрасный день на пути видоизменения типовой конфигурации я достиг этапа, когда основной
проблемой, отравляющей моё существование в рабочее время, стало жалобное нытьё пользователей по
поводу крайне медленного перелистывания формы списка справочника "Номенклатура",
в частности в процессе подбора товаров в расходную накладную и счёт.
Как оказалось, торможение было вызвано присутствием в этой самой форме трёх вычисляемых колонок, каждая
из которых обращалось к актуальным итогам одного из регистров: остатков товаров на складах, резервов
и заказов. К сожалению, непреодолимое желание воспользоваться рекомендацией 1С о замене вычисляемой
колонки на текстовое поле, было отвергнуто в категоричной форме: менеджер отдела сбыта должен иметь
возможность быстро оценивать ситуацию сразу по нескольким номенклатурным позициям, чтобы в случае
нехватки какого-нибудь товара предложить клиенту другой, имеющийся на складе.
Иногда торможение носило вопиющий характер, когда пользователь набирал, например, "эмаль" и несколько
секунд вынужден был ожидать, когда программа перемотает список товаров на букву "э".
Немного подумав, я определился с возможными вариантами выхода из кризиса:
- Оставить всё как есть, т.е. вычисляемые колонки с прямым обращением к регистрам;
- Попробовать в это же текстовое поле запихнуть SQL-запрос к БД 1С+MS SQL 2000;
- Сделать поля, вычисляемые в колонках, реквизитами справочника "Номенклатура" и изменять их в
процессе проведения документов;
- Организовать отдельную БД какого-нибудь формата специально для хранения актуальных остатков по
соответствующим регистрам. Опять же, придётся использовать текстовое поле с запросом к этой
дополнительной БД и обращаться к ней при проведении некоторых документов.
После этого начался этап экспериментов и творческих изысканий. Испытания проводились на
учебной БД MSSQL, и их результаты можно только приблизительно считать объективными, потому что
с базой я работал один, а не в компании исступлённо долбящих по клавиатуре менеджеров отдела сбыта.
Первый способ был оставлен про запас на случай, если ничего более удачного придумать не удастся.
Испытания второго привели к плачевным результатам. Была написана функция, возвращающая средствами
ADO остаток товара на складе. После попытки применить эту функцию торможение не только не исчезло,
а напротив, усугубилось.
Третий вариант, как я и предполагал, оказался самым быстрым. Однако я решил, что испытаю его на
живой базе, если только четвёртый способ не принесёт желаемого эффекта. Дело в том, что внесение
дополнительных реквизитов в справочник товаров вступало в противоречие с моими представлениями о
гармонии окружающего мира. "Неужели", думал я, "мне придётся нагружать
бедный справочник, к которому ежесекундно обращаются все, кому не лень, информацией, которая и так есть
в базе данных?".
Я решил не рисковать своим психическим здоровьем и немедленно приступил к исследованию оставшегося,
чётвёртого варианта.
По этой же причине, чтобы у читателя не возникало чувства неловкости или дискомфорта, сразу скажу,
что попаданием в десятку оказался последний способ. По крайней мере, полученный с его помощью
результат удовлетворил как меня, так и пользователей. Далее речь пойдёт о методике его внедрения.
Но сначала позвольте продемонстрировать небольшую сравнительную табличку, в которой приведено время
перелистывания справочника каждым из способов:
Способ |
Время на строку, сек |
вычисляемое текстовое поле |
0.019 |
SQL-запрос к БД |
>0.100 |
дополнительные реквизиты |
0.004 |
отдельная БД |
0.007 |
Итак, внимание, описание четвёртого способа.
Для простоты будем считать, что нам нужно ускорить только одну вычисляемую колонку остаток
товара. А ещё будем считать, что регистр "Остатки товаров" состоит из измерения "Товар" и ресурса
"Остаток". В качестве хранилища была выбрана СУБД MySQL.
Вот, что мне пришлось сделать:
- Установить MySQL 3.23.49 на сервер. "Установить" значить запустить дистрибутив и
обеспечить постоянную работу того, что из этого дистрибутива получилось. В результате на
сервере должен постоянно висеть служба MySQL, которая будет реагировать на запросы клиентов;
- Установить на всех рабочих станциях MyODBC 3.51.04, чтобы, как это принято называть, "обращаться
к базе данных средствами ADO", т.е. к серверу MySQL из предыдущего пункта;
- Написать обработку, которая создаёт, заполняет и удаляет базу данных MySQL. В нашем примере БД MySQL
состоит всего из одной таблицы с двумя столбцами. Первый столбец ID предназначен для хранения
уникального числа (для синхронизации номенклатуры). Второй содержит текущий остаток товара. С помощью
обработки, я создал БД MySQL с таблицей и заполнил её данными;
- Создать в Конфигураторе новую константу СерверMySQL для хранения IP-адреса компьютера, на котором
запущен MySQL-сервер. Соответственно, после этого войти в 1С и заполнить её значение;
- Внести в глобальный модуль пару переменных и процедур. Они предназначены для подключения к БД MySQL
и изменения в ней столбца с остатком в процессе проведения документов. Соответствующий кусок кода
с комментариями помещён в обработку из (3).
- Видоизменить модули всех документов, влияющих на остатки товаров. Не знаю, как у вас, а в моём
случае это были расходная и приходная накладные, перемещение, списание, ввод остатков товаров и
инвентаризация. Код получился примерно таким (см. также приложенный к статье пример, ссылка внизу
страницы):
Процедура ОбработкаПроведения()
//алгоритм проведения
ОбновитьMySQL(Контекст);
КонецПроцедуры
//=============================
Процедура ОбработкаУдаленияПроведения()
//алгоритм снятия с проведения
ОбновитьMySQL(Контекст);
КонецПроцедуры
|
Таким образом, мы синхронизируем изменение регистра в 1С и БД MySQL;
- В предопределённую процедуру ПриЗаписи() тех же видов документов вставить вызов
процедуры ЗапомнитьТЧДокументаПередЗаписью(Контекст). Это необходимо для того, чтобы не
потерять из поля зрения товары, которые будут удалены или заменены другими в процессе редактирования
документа;
- И, наконец, записать в форму списка справочника "Номенклатура" функцию
Функция ОптОст()
глКоманда.CommandText = "select * from rest_t WHERE ID='" +
Ид_Число (ТекущийЭлемент()) + "'";
Запись = глКоманда.Execute();
Если Запись.Eof = 0 Тогда
Возврат 0 + Запись.Fields("REST").Value
Иначе
Возврат 0;
КонецЕсли;
КонецФункции
|
и использовать её в вычисляемой текстовой колонке вместо старого выражения. Кроме этого, в
предопределённую процедуру формы ПриОткрытии() необходимо вставить вызов функции
ПодключениеMySQL().
Как я уже намекал, в результате всех этих манипуляций скорость перелистывания справочника товаров
возросла примерно втрое, и стала вполне приемлемой для нормальной работы.
Резюме: если у вас тормозит справочник с вычисляемыми колонками, почему бы вам не попробовать разогнать
его описанным способом? ;-)
С удовольствием по мере сил отвечу на вопросы и постараюсь адекватно воспринять замечания
и критику. Пишите.
|