Hare.ru @ Коллективный разум / Hare.ru @ Дикое место

Архив hare.ru 
Мысли, конвертированные в текст

Собственные руки TM


Все статьи раздела

Форма списка: листаем быстро

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С о замене вычисляемой колонки на текстовое поле, было отвергнуто в категоричной форме: менеджер отдела сбыта должен иметь возможность быстро оценивать ситуацию сразу по нескольким номенклатурным позициям, чтобы в случае нехватки какого-нибудь товара предложить клиенту другой, имеющийся на складе.

Иногда торможение носило вопиющий характер, когда пользователь набирал, например, "эмаль" и несколько секунд вынужден был ожидать, когда программа перемотает список товаров на букву "э".

Немного подумав, я определился с возможными вариантами выхода из кризиса:

  1. Оставить всё как есть, т.е. вычисляемые колонки с прямым обращением к регистрам;
  2. Попробовать в это же текстовое поле запихнуть SQL-запрос к БД 1С+MS SQL 2000;
  3. Сделать поля, вычисляемые в колонках, реквизитами справочника "Номенклатура" и изменять их в процессе проведения документов;
  4. Организовать отдельную БД какого-нибудь формата специально для хранения актуальных остатков по соответствующим регистрам. Опять же, придётся использовать текстовое поле с запросом к этой дополнительной БД и обращаться к ней при проведении некоторых документов.
После этого начался этап экспериментов и творческих изысканий. Испытания проводились на учебной БД MSSQL, и их результаты можно только приблизительно считать объективными, потому что с базой я работал один, а не в компании исступлённо долбящих по клавиатуре менеджеров отдела сбыта.

Первый способ был оставлен про запас на случай, если ничего более удачного придумать не удастся.

Испытания второго привели к плачевным результатам. Была написана функция, возвращающая средствами ADO остаток товара на складе. После попытки применить эту функцию торможение не только не исчезло, а напротив, усугубилось.

Третий вариант, как я и предполагал, оказался самым быстрым. Однако я решил, что испытаю его на живой базе, если только четвёртый способ не принесёт желаемого эффекта. Дело в том, что внесение дополнительных реквизитов в справочник товаров вступало в противоречие с моими представлениями о гармонии окружающего мира. "Неужели", – думал я, – "мне придётся нагружать бедный справочник, к которому ежесекундно обращаются все, кому не лень, информацией, которая и так есть в базе данных?".

Я решил не рисковать своим психическим здоровьем и немедленно приступил к исследованию оставшегося, чётвёртого варианта.

По этой же причине, чтобы у читателя не возникало чувства неловкости или дискомфорта, сразу скажу, что попаданием в десятку оказался последний способ. По крайней мере, полученный с его помощью результат удовлетворил как меня, так и пользователей. Далее речь пойдёт о методике его внедрения.

Но сначала позвольте продемонстрировать небольшую сравнительную табличку, в которой приведено время перелистывания справочника каждым из способов:

Способ Время на строку, сек
вычисляемое текстовое поле 0.019
SQL-запрос к БД >0.100
дополнительные реквизиты 0.004
отдельная БД 0.007

Итак, внимание, описание четвёртого способа.

Для простоты будем считать, что нам нужно ускорить только одну вычисляемую колонку – остаток товара. А ещё будем считать, что регистр "Остатки товаров" состоит из измерения "Товар" и ресурса "Остаток". В качестве хранилища была выбрана СУБД MySQL.

Вот, что мне пришлось сделать:

  1. Установить MySQL 3.23.49 на сервер. "Установить" – значить запустить дистрибутив и обеспечить постоянную работу того, что из этого дистрибутива получилось. В результате на сервере должен постоянно висеть служба MySQL, которая будет реагировать на запросы клиентов;
  2. Установить на всех рабочих станциях MyODBC 3.51.04, чтобы, как это принято называть, "обращаться к базе данных средствами ADO", т.е. к серверу MySQL из предыдущего пункта;
  3. Написать обработку, которая создаёт, заполняет и удаляет базу данных MySQL. В нашем примере БД MySQL состоит всего из одной таблицы с двумя столбцами. Первый столбец ID предназначен для хранения уникального числа (для синхронизации номенклатуры). Второй содержит текущий остаток товара. С помощью обработки, я создал БД MySQL с таблицей и заполнил её данными;
  4. Создать в Конфигураторе новую константу СерверMySQL для хранения IP-адреса компьютера, на котором запущен MySQL-сервер. Соответственно, после этого – войти в 1С и заполнить её значение;
  5. Внести в глобальный модуль пару переменных и процедур. Они предназначены для подключения к БД MySQL и изменения в ней столбца с остатком в процессе проведения документов. Соответствующий кусок кода с комментариями помещён в обработку из (3).
  6. Видоизменить модули всех документов, влияющих на остатки товаров. Не знаю, как у вас, а в моём случае это были расходная и приходная накладные, перемещение, списание, ввод остатков товаров и инвентаризация. Код получился примерно таким (см. также приложенный к статье пример, ссылка внизу страницы):

    Процедура ОбработкаПроведения()
      //алгоритм проведения
      ОбновитьMySQL(Контекст);
    КонецПроцедуры
    //=============================
    Процедура ОбработкаУдаленияПроведения()
      //алгоритм снятия с проведения
      ОбновитьMySQL(Контекст);
    КонецПроцедуры

    Таким образом, мы синхронизируем изменение регистра в 1С и БД MySQL;

  7. В предопределённую процедуру ПриЗаписи() тех же видов документов вставить вызов процедуры ЗапомнитьТЧДокументаПередЗаписью(Контекст). Это необходимо для того, чтобы не потерять из поля зрения товары, которые будут удалены или заменены другими в процессе редактирования документа;
  8. И, наконец, записать в форму списка справочника "Номенклатура" функцию

    Функция ОптОст()   глКоманда.CommandText = "select * from rest_t WHERE ID='" +
      Ид_Число (ТекущийЭлемент()) + "'";
      Запись = глКоманда.Execute();
      Если Запись.Eof = 0 Тогда
        Возврат 0 + Запись.Fields("REST").Value
      Иначе
        Возврат 0;
      КонецЕсли;
    КонецФункции

    и использовать её в вычисляемой текстовой колонке вместо старого выражения. Кроме этого, в предопределённую процедуру формы ПриОткрытии() необходимо вставить вызов функции ПодключениеMySQL().

Как я уже намекал, в результате всех этих манипуляций скорость перелистывания справочника товаров возросла примерно втрое, и стала вполне приемлемой для нормальной работы.

Резюме: если у вас тормозит справочник с вычисляемыми колонками, почему бы вам не попробовать разогнать его описанным способом? ;-)

С удовольствием по мере сил отвечу на вопросы и постараюсь адекватно воспринять замечания и критику. Пишите.

Партнеры:


Также может быть интересно:

Канал Россия 1 на http://spbtvonline.ru/
   
 Сайт поддерживается за счет партнеров:
:::... Сайт содержит архив двух версий hare.ru Карта сайта