Буду краток. В процедуре УчетНДС.ОпределитьНаличиеСчетовФактурПолученных был изменен способ обращения к временной таблице счетов-фактур, использующейся для отбора при выборке из физических таблиц документов. Условие "ГДЕ Ссылка В (ВЫБРАТЬ ...)" было преобразовано во внутреннее соединение:
ТекстЗапроса = ТекстЗапроса + ТекстРазделителяЗапросовПакета +
"ВЫБРАТЬ
| ВременнаяТаблицаОстатки.СчетФактура КАК СчетФактура
|ПОМЕСТИТЬ ВременнаяТаблицаСчетФактуры
|ИЗ
| ВременнаяТаблицаОстатки КАК ВременнаяТаблицаОстатки
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| ВременнаяТаблицаОстатки.ИсправленныйСчетФактура
|ИЗ
| ВременнаяТаблицаОстатки КАК ВременнаяТаблицаОстатки
|
|ИНДЕКСИРОВАТЬ ПО
| СчетФактура
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| СчетаФактурыДокументы.СчетФактура КАК СчетФактура,
| СчетаФактурыДокументы.ССылка КАК ССылка,
| СчетаФактурыДокументы.ДокументОснование КАК ДокументОснование,
| СчетаФактурыДокументы.СчетФактураПроведен КАК СчетФактураПроведен,
| СчетаФактурыДокументы.СчетФактураДата КАК СчетФактураДата
|ПОМЕСТИТЬ ВременнаяТаблицаСчетФактураПолученный
|ИЗ
| (ВЫБРАТЬ
| СчетФактураПолученный.Ссылка КАК СчетФактура,
| СчетФактураПолученный.Ссылка КАК ССылка,
| СчетФактураПолученный.ДокументОснование КАК ДокументОснование,
| СчетФактураПолученный.Ссылка.Проведен КАК СчетФактураПроведен,
| СчетФактураПолученный.Ссылка.Дата КАК СчетФактураДата
| ИЗ
| Документ.СчетФактураПолученный.ДокументыОснования КАК СчетФактураПолученный
//--> ДОРАБОТКА - добавляем внутреннее соединение
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВременнаяТаблицаСчетФактуры КАК ВременнаяТаблицаСчетФактуры ПО СчетФактураПолученный.Ссылка = ВременнаяТаблицаСчетФактуры.СчетФактура
//<-- ДОРАБОТКА - добавляем внутреннее соединение
| ГДЕ
//--> ДОРАБОТКА - отключаем условие "В"
//| СчетФактураПолученный.Ссылка В
//| (ВЫБРАТЬ
//| ВременнаяТаблицаСчетФактуры.СчетФактура
//| ИЗ
//| ВременнаяТаблицаСчетФактуры)
//| И
//<-- ДОРАБОТКА - отключаем условие "В"
| СчетФактураПолученный.Ссылка.Организация = &Организация
|
| ОБЪЕДИНИТЬ ВСЕ
|..."
(пример исправления привел только для одного блока процедуры, самого критичного для производительности в моем случае - все остальные изменения по тексту процедуры отднотипны)
В результате этих изменений MSQL Server стал строить эффективный план запроса, с использованием всех доступных ему индексов, чего, к сожалению, не удавалось добиться при типовом написании запроса.
План запроса до оптимизации:
Видим, что на каждом этапе происходит сканирование таблиц без использования индексов. Две большие таблицы 121 тыс. строк и 48 тыс. строк соединяются перебором в цикле и количество обработанных строк доходит до 6 миллиардов при всего 3-х строках в конечной выборке.
План запроса после оптимизации:
Здесь все красиво - исходные таблицы сразу отфильтрованы по индексу и на всем протяжении происходит обработка всего 3-х строк.
На моей базе (SQL Server 2005) время выполнения запроса уменьшилось с порядка 2000-3000 секунд до 10-30 секунд. Как на Вашей конкретной базе сработает оптимизатор - это вопрос, но, если скорость заполнения у Вас катастрофически низкая, то попробовать методику стоит.
Для себя из этой истории я сделал один простой вывод - использовать условие "ГДЕ В ()" надо очень и очень аккуратно, особенно в условиях неявных соединений нескольких физических таблиц (в данном случае соединялись таблицы документа и его табличной части ДокументыОснования). Не помог даже тот факт, что временная таблица СФ была проиндексирована - оптимизатор совершенно проигнорировал этот факт и не воспользовался преимуществом индекса.
См. также: Ускоряем формирование отчета "Книга покупок"
К публикации приложена внешняя обработка заполнения табличной части "Вычет по приобретенным ценностям" документа (создана на базе релиза Бухгалтерия предприятия КОРП 2.0.64.35) .