Итак, с помощью отладчика была обнаружена функция "ПолучитьДополнительнуюИнформациюПоСФДляКнигиПокупок", располагающаяся в общем модуле "УчетНДС" (или непосредственно в модуле отчета, в зависимости от версии отчета). Эта функция запросом собирает данные по всем номерам ГТД и странам происхождения товаров по списку документов, переданному в качестве параметра. Запрос состоит из множества подзапросов по табличным частям документов различных типов, объединенных через "ОБЪЕДИНИТЬ ВСЕ" и в каждом из этих подзапросов повторяется одно единственное условие "... ТаблицаТоваров.Ссылка В (&СписокСФ)":
// Дополнение по ГТД и стране происхождения
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| ТаблицаТоваров.Ссылка КАК СчетФактура,
| ТаблицаТоваров.СтранаПроисхождения.Код КАК СтранаПроисхождения,
| ТаблицаТоваров.НомерГТД,
| СУММА(1) КАК КоличествоЭлементов
|ИЗ
| Документ.ПоступлениеТоваровУслуг.Товары КАК ТаблицаТоваров
|ГДЕ
| ТаблицаТоваров.Ссылка В(&СписокСФ)
|
|СГРУППИРОВАТЬ ПО
| ТаблицаТоваров.Ссылка,
| ТаблицаТоваров.СтранаПроисхождения,
| ТаблицаТоваров.НомерГТД,
| ТаблицаТоваров.СтранаПроисхождения.Код
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| ТаблицаТоваров.Ссылка,
| ТаблицаТоваров.СтранаПроисхождения.Код,
| ТаблицаТоваров.НомерГТД,
| СУММА(1)
|ИЗ
| Документ.ПоступлениеТоваровУслуг.Оборудование КАК ТаблицаТоваров
|ГДЕ
| ТаблицаТоваров.Ссылка В(&СписокСФ)
|
|СГРУППИРОВАТЬ ПО
| ТаблицаТоваров.Ссылка,
| ТаблицаТоваров.СтранаПроисхождения,
| ТаблицаТоваров.НомерГТД,
| ТаблицаТоваров.СтранаПроисхождения.Код
Вот это условие меня и смутило. Ведь, как известно, условия с использованием "В" могут работать просто до неприличия долго, особенно, при большом количестве элементов в сравниваемом массиве.
Было решено немного переделать это безобразие, использовав для хранения списка документов проиндексированную временную таблицу, а вхождение документа в эту таблицу отрабатывать через "ВНУТРЕННЕЕ СОЕДИНЕНИЕ". Т.е. текст проблемного условия фактически заменяем на текст: "... ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТСписокСчетовФактур КАК СписокСчетовФактур ПО ТаблицаТоваров.Ссылка = СписокСчетовФактур.СчетФактура", где "СписокСчетовФактур" - это наша временная таблица.
Вот кусок кода, который преобразует исходный запрос:
Запрос.УстановитьПараметр("СписокСФ", СписокСчетовФактур);
//--> ДОРАБОТКА (замена в запросе условий "ГДЕ Документ В &СписокСФ" на "ВНУТРЕННЕЕ СОЕДИНЕНИЕ" к временной таблице)
//заменим тексты условий на наш текст с внутренним соединением
//если поле с именем "Ссылка"
Запрос.Текст = СтрЗаменить(Запрос.Текст, "ГДЕ
| ТаблицаТоваров.Ссылка В(&СписокСФ)",
"ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТСписокСчетовФактур КАК СписокСчетовФактур
| ПО ТаблицаТоваров.Ссылка = СписокСчетовФактур.СчетФактура");
//если поле с именем "СчетФактура"
Запрос.Текст = СтрЗаменить(Запрос.Текст, "ГДЕ
| ТаблицаТоваров.СчетФактура В(&СписокСФ)",
"ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТСписокСчетовФактур КАК СписокСчетовФактур
| ПО ТаблицаТоваров.СчетФактура = СписокСчетовФактур.СчетФактура");
//сформируем таблицу значений с одной единственной типизированной колонкой СчетФактура для передачи ее в качестве параметра запроса
ТаблицаСчетовФактур = Новый ТаблицаЗначений;
ТаблицаСчетовФактур.Колонки.Добавить("СчетФактура", Новый ОписаниеТипов(Документы.ТипВсеСсылки()));
Для Каждого СФ Из СписокСчетовФактур Цикл
ТаблицаСчетовФактур.Добавить().СчетФактура = СФ;
КонецЦикла;
Запрос.УстановитьПараметр("ТаблицаСчетовФактур", ТаблицаСчетовФактур);
//добавим в начало исходного запрос текст создания временной таблицы на основании ТЗ ТаблицаСчетовФактур, не забывая добавить индекс по полю СчетФактура
Запрос.Текст = "
|ВЫБРАТЬ СчетФактура КАК СчетФактура
|ПОМЕСТИТЬ ВТСписокСчетовФактур
|ИЗ &ТаблицаСчетовФактур КАК ТаблицаСчетовФактур
|ИНДЕКСИРОВАТЬ ПО СчетФактура
|;
|
|" + Запрос.Текст;
//
ГТДпоСФ = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
Итак, результаты замеров производительности - ~600 секунд до оптимизации запроса против ~4 секунд после (см. картинку в блоке скриншотов). Результаты были получены при количестве строк в книге покупок около 15 000. Приведен результат лишь одного сравнительного замера, хотя замеры делались несколько раз для исключения фактора везения :) Замеры были сделаны на "боевом" среднезагруженном SQL в рабочее время и результаты естественно немного разнились. Несмотря на все оговорки и прямолинейность методики тестирования, можно довольно уверенно констатировать, что профит от доработок довольно ощутим.
Примечания:
- информация, изложенная выше, скорее всего, имеет смысл только для довольно больших баз или при формировании книги за очень длительные периоды. Как уже упоминалось, в данном случае замеры делались на примере книги, состоящей из порядка 15 000 строк. На файловых базах не проверялось.
- в качестве подопытного выступал отчет "Книга покупок по Постановлению № 1137" (Бухгалтерия КОРП 2.0.46.5), но все изложенное, скорее всего, применимо и к другим версиям отчета, в т.ч. из других релизов. Во всяком случае, в Бухгалтерии 3.0 проблемная функция осталась неизменной.
См. также:
Ускоряем заполнение документа "Формирование записей книги покупок"
К публикации приложены доработанные версии отчетов "Книга покупок", "Книга покупок по Постановлению № 1137" , "Книга продаж по Постановлению № 1137" (Бухгалтерия КОРП 2.0).
Обновления:
30.10.2015 - добавлена версия отчета "Книга покупок по Постановлению № 1137" (Бухгалтерия предприятия КОРП 2.0.64.35)